From f0ca862c487b83a88608cd8725f8a931a1f39d40 Mon Sep 17 00:00:00 2001 From: JustCris Date: Tue, 5 Nov 2024 16:13:33 +0100 Subject: [PATCH 01/22] add currentFuelPercent to VehicleRentalVehicle and gtfs graphql API --- .../apis/gtfs/datafetchers/RentalVehicleImpl.java | 5 +++++ .../apis/gtfs/generated/GraphQLDataFetchers.java | 2 ++ .../service/vehiclerental/model/VehicleRentalVehicle.java | 5 +++++ .../datasources/GbfsFreeVehicleStatusMapper.java | 1 + .../org/opentripplanner/apis/gtfs/schema.graphqls | 2 ++ .../model/TestFreeFloatingRentalVehicleBuilder.java | 8 ++++++++ .../apis/gtfs/expectations/rental-vehicle.json | 3 ++- .../apis/gtfs/queries/rental-vehicle.graphql | 1 + 8 files changed, 26 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java index c4fb92c0ef4..5dec579e2e9 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java @@ -16,6 +16,11 @@ public DataFetcher allowPickupNow() { return environment -> getSource(environment).allowPickupNow(); } + @Override + public DataFetcher currentFuelPercent() { + return environment -> getSource(environment).getCurrentFuelPercent(); + } + @Override public DataFetcher id() { return environment -> diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 9c95ea65e91..b2391accd64 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -897,6 +897,8 @@ public interface GraphQLRentalPlace extends TypeResolver {} public interface GraphQLRentalVehicle { public DataFetcher allowPickupNow(); + public DataFetcher currentFuelPercent(); + public DataFetcher id(); public DataFetcher lat(); diff --git a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java index 042e608c88f..2838ec43ea1 100644 --- a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java +++ b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java @@ -25,6 +25,7 @@ public class VehicleRentalVehicle implements VehicleRentalPlace { public Double currentRangeMeters; public VehicleRentalStation station; public String pricingPlanId; + public Double currentFuelPercent; @Override public FeedScopedId getId() { @@ -133,4 +134,8 @@ public VehicleRentalStationUris getRentalUris() { public VehicleRentalSystem getVehicleRentalSystem() { return system; } + + public Double getCurrentFuelPercent() { + return currentFuelPercent; + } } diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index 959521e017e..873bff1f8ff 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -61,6 +61,7 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { String webUri = rentalUris.getWeb(); rentalVehicle.rentalUris = new VehicleRentalStationUris(androidUri, iosUri, webUri); } + rentalVehicle.currentFuelPercent = vehicle.getCurrentFuelPercent(); return rentalVehicle; } else { diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 537d9b680b4..a57631df69c 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -1874,6 +1874,8 @@ type RealTimeEstimate { type RentalVehicle implements Node & PlaceInterface { "If true, vehicle is currently available for renting." allowPickupNow: Boolean + "Current fuel percentage of the free floating vehicle. Value expressed from 0 to 1" + currentFuelPercent: Float "Global object ID provided by Relay. This value can be used to refetch this object using **node** query." id: ID! "Latitude of the vehicle (WGS 84)" diff --git a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java index a9b2398f686..c0787b73493 100644 --- a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java +++ b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java @@ -9,9 +9,11 @@ public class TestFreeFloatingRentalVehicleBuilder { public static final String NETWORK_1 = "Network-1"; public static final double DEFAULT_LATITUDE = 47.520; public static final double DEFAULT_LONGITUDE = 19.01; + public static final double DEFAULT_CURRENT_FUEL_PERCENT = 0.5; private double latitude = DEFAULT_LATITUDE; private double longitude = DEFAULT_LONGITUDE; + private double currentFuelPercent = DEFAULT_CURRENT_FUEL_PERCENT; private VehicleRentalSystem system = null; private RentalVehicleType vehicleType = RentalVehicleType.getDefaultType(NETWORK_1); @@ -30,6 +32,11 @@ public TestFreeFloatingRentalVehicleBuilder withLongitude(double longitude) { return this; } + public TestFreeFloatingRentalVehicleBuilder withCurrentFuelPercent(double currentFuelPercent) { + this.currentFuelPercent = currentFuelPercent; + return this; + } + public TestFreeFloatingRentalVehicleBuilder withSystem(String id, String url) { this.system = new VehicleRentalSystem( @@ -85,6 +92,7 @@ public VehicleRentalVehicle build() { vehicle.longitude = longitude; vehicle.vehicleType = vehicleType; vehicle.system = system; + vehicle.currentFuelPercent = currentFuelPercent; return vehicle; } } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json index bcff74d0413..6036df5c12b 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json @@ -15,7 +15,8 @@ "rentalNetwork": { "networkId": "Network-1", "url": "https://foo.bar" - } + }, + "currentFuelPercent": 0.5 } } } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql index 9a912781c56..6460a11d801 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql @@ -19,5 +19,6 @@ networkId url } + currentFuelPercent } } From 4e13710cb0fcd63169240860a3df7dceafa92325 Mon Sep 17 00:00:00 2001 From: JustCris Date: Fri, 22 Nov 2024 16:34:03 +0100 Subject: [PATCH 02/22] add currentRangeMeters to VehicleRentalVehicle and gtfs graphql API --- .../apis/gtfs/datafetchers/RentalVehicleImpl.java | 5 +++++ .../apis/gtfs/generated/GraphQLDataFetchers.java | 2 ++ .../service/vehiclerental/model/VehicleRentalVehicle.java | 4 ++++ .../datasources/GbfsFreeVehicleStatusMapper.java | 2 +- .../org/opentripplanner/apis/gtfs/schema.graphqls | 4 +++- .../model/TestFreeFloatingRentalVehicleBuilder.java | 8 ++++++++ .../apis/gtfs/expectations/rental-vehicle.json | 3 ++- .../apis/gtfs/queries/rental-vehicle.graphql | 1 + 8 files changed, 26 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java index 5dec579e2e9..64cff3b44fb 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java @@ -21,6 +21,11 @@ public DataFetcher currentFuelPercent() { return environment -> getSource(environment).getCurrentFuelPercent(); } + @Override + public DataFetcher currentRangeMeters() { + return environment -> getSource(environment).getCurrentRangeMeters(); + } + @Override public DataFetcher id() { return environment -> diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index b2391accd64..b1d2f32ffda 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -899,6 +899,8 @@ public interface GraphQLRentalVehicle { public DataFetcher currentFuelPercent(); + public DataFetcher currentRangeMeters(); + public DataFetcher id(); public DataFetcher lat(); diff --git a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java index 2838ec43ea1..ee5316f0526 100644 --- a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java +++ b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java @@ -138,4 +138,8 @@ public VehicleRentalSystem getVehicleRentalSystem() { public Double getCurrentFuelPercent() { return currentFuelPercent; } + + public Double getCurrentRangeMeters() { + return currentRangeMeters; + } } diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index 873bff1f8ff..f3c60307ef9 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -53,6 +53,7 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { ? Instant.ofEpochSecond((long) (double) vehicle.getLastReported()) : null; rentalVehicle.currentRangeMeters = vehicle.getCurrentRangeMeters(); + rentalVehicle.currentFuelPercent = vehicle.getCurrentFuelPercent(); rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); GBFSRentalUris rentalUris = vehicle.getRentalUris(); if (rentalUris != null) { @@ -61,7 +62,6 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { String webUri = rentalUris.getWeb(); rentalVehicle.rentalUris = new VehicleRentalStationUris(androidUri, iosUri, webUri); } - rentalVehicle.currentFuelPercent = vehicle.getCurrentFuelPercent(); return rentalVehicle; } else { diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index a57631df69c..aa42cd6e7fa 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -1874,8 +1874,10 @@ type RealTimeEstimate { type RentalVehicle implements Node & PlaceInterface { "If true, vehicle is currently available for renting." allowPickupNow: Boolean - "Current fuel percentage of the free floating vehicle. Value expressed from 0 to 1" + "Fuel or battery power remaining in the vehicle. Expressed from 0 to 1." currentFuelPercent: Float + "Range in meters that the vehicle can travel with the vehicle's current charge or fuel." + currentRangeMeters: Float "Global object ID provided by Relay. This value can be used to refetch this object using **node** query." id: ID! "Latitude of the vehicle (WGS 84)" diff --git a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java index c0787b73493..1a54b24bcf2 100644 --- a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java +++ b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java @@ -10,10 +10,12 @@ public class TestFreeFloatingRentalVehicleBuilder { public static final double DEFAULT_LATITUDE = 47.520; public static final double DEFAULT_LONGITUDE = 19.01; public static final double DEFAULT_CURRENT_FUEL_PERCENT = 0.5; + public static final double DEFAULT_CURRENT_RANGE_METERS = 5500; private double latitude = DEFAULT_LATITUDE; private double longitude = DEFAULT_LONGITUDE; private double currentFuelPercent = DEFAULT_CURRENT_FUEL_PERCENT; + private double currentRangeMeters = DEFAULT_CURRENT_RANGE_METERS; private VehicleRentalSystem system = null; private RentalVehicleType vehicleType = RentalVehicleType.getDefaultType(NETWORK_1); @@ -37,6 +39,11 @@ public TestFreeFloatingRentalVehicleBuilder withCurrentFuelPercent(double curren return this; } + public TestFreeFloatingRentalVehicleBuilder withCurrentRangeMeters(double currentRangeMeters) { + this.currentRangeMeters = currentRangeMeters; + return this; + } + public TestFreeFloatingRentalVehicleBuilder withSystem(String id, String url) { this.system = new VehicleRentalSystem( @@ -93,6 +100,7 @@ public VehicleRentalVehicle build() { vehicle.vehicleType = vehicleType; vehicle.system = system; vehicle.currentFuelPercent = currentFuelPercent; + vehicle.currentRangeMeters = currentRangeMeters; return vehicle; } } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json index 6036df5c12b..e8e532bedcc 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json @@ -16,7 +16,8 @@ "networkId": "Network-1", "url": "https://foo.bar" }, - "currentFuelPercent": 0.5 + "currentFuelPercent": 0.5, + "currentRangeMeters": 5500.0 } } } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql index 6460a11d801..5fd8da8c5fd 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql @@ -20,5 +20,6 @@ url } currentFuelPercent + currentRangeMeters } } From 644f7840d8b70477dbb7c07a022caba85ddd65fe Mon Sep 17 00:00:00 2001 From: JustCris Date: Fri, 22 Nov 2024 17:18:29 +0100 Subject: [PATCH 03/22] fix comment typo --- .../resources/org/opentripplanner/apis/gtfs/schema.graphqls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index aa42cd6e7fa..3f4b8984f14 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -1876,7 +1876,7 @@ type RentalVehicle implements Node & PlaceInterface { allowPickupNow: Boolean "Fuel or battery power remaining in the vehicle. Expressed from 0 to 1." currentFuelPercent: Float - "Range in meters that the vehicle can travel with the vehicle's current charge or fuel." + "Range in meters that the vehicle can travel with the current charge or fuel." currentRangeMeters: Float "Global object ID provided by Relay. This value can be used to refetch this object using **node** query." id: ID! From 062a907de8122038e3f5e6e917dbbc49df2d705a Mon Sep 17 00:00:00 2001 From: JustCris Date: Mon, 2 Dec 2024 16:21:40 +0100 Subject: [PATCH 04/22] use Distance class for currentRangeMeters --- .../ext/fares/impl/GtfsFaresV2ServiceTest.java | 2 +- .../org/opentripplanner/ext/fares/model/FareDistance.java | 2 ++ .../apis/gtfs/datafetchers/RentalVehicleImpl.java | 5 ++++- .../org/opentripplanner/gtfs/mapping/FareLegRuleMapper.java | 2 +- .../service/vehiclerental/model/VehicleRentalVehicle.java | 5 +++-- .../org/opentripplanner/transit/model/basic}/Distance.java | 2 +- .../datasources/GbfsFreeVehicleStatusMapper.java | 5 ++++- .../opentripplanner/gtfs/mapping/FareLegRuleMapperTest.java | 2 +- .../model/TestFreeFloatingRentalVehicleBuilder.java | 3 ++- 9 files changed, 19 insertions(+), 9 deletions(-) rename application/src/{ext/java/org/opentripplanner/ext/fares/model => main/java/org/opentripplanner/transit/model/basic}/Distance.java (96%) diff --git a/application/src/ext-test/java/org/opentripplanner/ext/fares/impl/GtfsFaresV2ServiceTest.java b/application/src/ext-test/java/org/opentripplanner/ext/fares/impl/GtfsFaresV2ServiceTest.java index 19b55489778..a7b2694e2e8 100644 --- a/application/src/ext-test/java/org/opentripplanner/ext/fares/impl/GtfsFaresV2ServiceTest.java +++ b/application/src/ext-test/java/org/opentripplanner/ext/fares/impl/GtfsFaresV2ServiceTest.java @@ -12,7 +12,7 @@ import java.util.Set; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.opentripplanner.ext.fares.model.Distance; +import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.ext.fares.model.FareDistance; import org.opentripplanner.ext.fares.model.FareDistance.LinearDistance; import org.opentripplanner.ext.fares.model.FareLegRule; diff --git a/application/src/ext/java/org/opentripplanner/ext/fares/model/FareDistance.java b/application/src/ext/java/org/opentripplanner/ext/fares/model/FareDistance.java index 9c18e3947b3..bbbc5e64426 100644 --- a/application/src/ext/java/org/opentripplanner/ext/fares/model/FareDistance.java +++ b/application/src/ext/java/org/opentripplanner/ext/fares/model/FareDistance.java @@ -1,5 +1,7 @@ package org.opentripplanner.ext.fares.model; +import org.opentripplanner.transit.model.basic.Distance; + /** Represents a distance metric used in distance-based fare computation*/ public sealed interface FareDistance { /** Represents the number of stops as a distance metric in fare computation */ diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java index 64cff3b44fb..4d1787219b4 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java @@ -23,7 +23,10 @@ public DataFetcher currentFuelPercent() { @Override public DataFetcher currentRangeMeters() { - return environment -> getSource(environment).getCurrentRangeMeters(); + return environment -> + getSource(environment).getCurrentRangeMeters() != null + ? getSource(environment).getCurrentRangeMeters().toMeters() + : null; } @Override diff --git a/application/src/main/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapper.java b/application/src/main/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapper.java index 2218be9cf30..b67b4944cae 100644 --- a/application/src/main/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapper.java +++ b/application/src/main/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapper.java @@ -4,7 +4,7 @@ import java.util.Collection; import java.util.Objects; -import org.opentripplanner.ext.fares.model.Distance; +import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.ext.fares.model.FareDistance; import org.opentripplanner.ext.fares.model.FareLegRule; import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore; diff --git a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java index ee5316f0526..b8161ed8fe9 100644 --- a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java +++ b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java @@ -4,6 +4,7 @@ import java.util.Set; import org.opentripplanner.framework.i18n.I18NString; import org.opentripplanner.street.model.RentalFormFactor; +import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.transit.model.framework.FeedScopedId; /** @@ -22,7 +23,7 @@ public class VehicleRentalVehicle implements VehicleRentalPlace { public boolean isReserved = false; public boolean isDisabled = false; public Instant lastReported; - public Double currentRangeMeters; + public Distance currentRangeMeters; public VehicleRentalStation station; public String pricingPlanId; public Double currentFuelPercent; @@ -139,7 +140,7 @@ public Double getCurrentFuelPercent() { return currentFuelPercent; } - public Double getCurrentRangeMeters() { + public Distance getCurrentRangeMeters() { return currentRangeMeters; } } diff --git a/application/src/ext/java/org/opentripplanner/ext/fares/model/Distance.java b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java similarity index 96% rename from application/src/ext/java/org/opentripplanner/ext/fares/model/Distance.java rename to application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java index f30712d4cad..ce2654b0fbb 100644 --- a/application/src/ext/java/org/opentripplanner/ext/fares/model/Distance.java +++ b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java @@ -1,4 +1,4 @@ -package org.opentripplanner.ext.fares.model; +package org.opentripplanner.transit.model.basic; import org.opentripplanner.utils.tostring.ValueObjectToStringBuilder; diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index f3c60307ef9..975ce4cebd1 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -13,6 +13,7 @@ import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; import org.opentripplanner.service.vehiclerental.model.VehicleRentalSystem; import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle; +import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.transit.model.framework.FeedScopedId; public class GbfsFreeVehicleStatusMapper { @@ -52,8 +53,10 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { vehicle.getLastReported() != null ? Instant.ofEpochSecond((long) (double) vehicle.getLastReported()) : null; - rentalVehicle.currentRangeMeters = vehicle.getCurrentRangeMeters(); rentalVehicle.currentFuelPercent = vehicle.getCurrentFuelPercent(); + Double currentRangeMeters = vehicle.getCurrentRangeMeters(); + rentalVehicle.currentRangeMeters = + currentRangeMeters != null ? Distance.ofMeters(currentRangeMeters) : null; rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); GBFSRentalUris rentalUris = vehicle.getRentalUris(); if (rentalUris != null) { diff --git a/application/src/test/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapperTest.java b/application/src/test/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapperTest.java index dbe833a7aaa..4fdf17effb9 100644 --- a/application/src/test/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapperTest.java +++ b/application/src/test/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapperTest.java @@ -12,7 +12,7 @@ import org.onebusaway.gtfs.model.FareLegRule; import org.onebusaway.gtfs.model.FareMedium; import org.onebusaway.gtfs.model.FareProduct; -import org.opentripplanner.ext.fares.model.Distance; +import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.ext.fares.model.FareDistance; import org.opentripplanner.ext.fares.model.FareDistance.LinearDistance; import org.opentripplanner.ext.fares.model.FareDistance.Stops; diff --git a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java index 1a54b24bcf2..28d1a62503c 100644 --- a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java +++ b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java @@ -2,6 +2,7 @@ import org.opentripplanner.framework.i18n.NonLocalizedString; import org.opentripplanner.street.model.RentalFormFactor; +import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.transit.model.framework.FeedScopedId; public class TestFreeFloatingRentalVehicleBuilder { @@ -100,7 +101,7 @@ public VehicleRentalVehicle build() { vehicle.vehicleType = vehicleType; vehicle.system = system; vehicle.currentFuelPercent = currentFuelPercent; - vehicle.currentRangeMeters = currentRangeMeters; + vehicle.currentRangeMeters = Distance.ofMeters(currentRangeMeters); return vehicle; } } From 7d12fcdf529b586434df2c29f3939b9de2238a66 Mon Sep 17 00:00:00 2001 From: JustCris Date: Mon, 2 Dec 2024 17:08:57 +0100 Subject: [PATCH 05/22] add greater and less than methods for Distance --- .../transit/model/basic/Distance.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java index ce2654b0fbb..86335cbdb64 100644 --- a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java +++ b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java @@ -1,5 +1,6 @@ package org.opentripplanner.transit.model.basic; +import java.util.Objects; import org.opentripplanner.utils.tostring.ValueObjectToStringBuilder; public class Distance { @@ -27,6 +28,20 @@ public double toMeters() { return this.meters; } + /** + * Is this distance greater than the one passed in + */ + public boolean greaterThan(Distance distance) { + return this.meters > distance.meters; + } + + /** + * Is this distance less than the one passed in + */ + public boolean lessThan(Distance distance) { + return this.meters < distance.meters; + } + @Override public boolean equals(Object other) { if (other instanceof Distance distance) { @@ -36,6 +51,11 @@ public boolean equals(Object other) { } } + @Override + public int hashCode() { + return Objects.hash(meters, 31); + } + @Override public String toString() { if (meters < METERS_PER_KM) { From 95cdf38bf3dd2893ab3d2b02e4e7dac33661793f Mon Sep 17 00:00:00 2001 From: JustCris Date: Mon, 2 Dec 2024 17:09:08 +0100 Subject: [PATCH 06/22] Distance class tests --- .../gtfs/mapping/FareLegRuleMapper.java | 2 +- .../gtfs/mapping/FareLegRuleMapperTest.java | 2 +- .../routing/core/DistanceTest.java | 47 +++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java diff --git a/application/src/main/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapper.java b/application/src/main/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapper.java index b67b4944cae..e24aa300406 100644 --- a/application/src/main/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapper.java +++ b/application/src/main/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapper.java @@ -4,10 +4,10 @@ import java.util.Collection; import java.util.Objects; -import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.ext.fares.model.FareDistance; import org.opentripplanner.ext.fares.model.FareLegRule; import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore; +import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.transit.model.framework.FeedScopedId; public final class FareLegRuleMapper { diff --git a/application/src/test/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapperTest.java b/application/src/test/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapperTest.java index 4fdf17effb9..890da8264f4 100644 --- a/application/src/test/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapperTest.java +++ b/application/src/test/java/org/opentripplanner/gtfs/mapping/FareLegRuleMapperTest.java @@ -12,11 +12,11 @@ import org.onebusaway.gtfs.model.FareLegRule; import org.onebusaway.gtfs.model.FareMedium; import org.onebusaway.gtfs.model.FareProduct; -import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.ext.fares.model.FareDistance; import org.opentripplanner.ext.fares.model.FareDistance.LinearDistance; import org.opentripplanner.ext.fares.model.FareDistance.Stops; import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore; +import org.opentripplanner.transit.model.basic.Distance; class FareLegRuleMapperTest { diff --git a/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java b/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java new file mode 100644 index 00000000000..5ec561916d5 --- /dev/null +++ b/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java @@ -0,0 +1,47 @@ +package org.opentripplanner.routing.core; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.opentripplanner.transit.model.basic.Distance; + +public class DistanceTest { + + private static final Distance oneThousandFiveHundredMeters = Distance.ofMeters(1500d); + private static final Distance onePointFiveKilometers = Distance.ofKilometers(1.5d); + private static final Distance twoKilometers = Distance.ofKilometers(2d); + private static final Distance oneHundredMeters = Distance.ofMeters(100d); + private static final Distance pointOneKilometer = Distance.ofKilometers(0.1d); + private static final Distance oneHundredPointFiveMeters = Distance.ofMeters(100.5d); + + @Test + void equals() { + assertEquals(oneThousandFiveHundredMeters, onePointFiveKilometers); + assertEquals(pointOneKilometer, oneHundredMeters); + assertNotEquals(oneHundredPointFiveMeters, oneHundredMeters); + assertNotEquals(twoKilometers, onePointFiveKilometers); + } + + @Test + void greaterThan() { + assertTrue(oneHundredPointFiveMeters.greaterThan(oneHundredMeters)); + assertTrue(twoKilometers.greaterThan(oneThousandFiveHundredMeters)); + assertFalse(oneThousandFiveHundredMeters.greaterThan(onePointFiveKilometers)); + } + + @Test + void lessThan() { + assertTrue(oneThousandFiveHundredMeters.lessThan(twoKilometers)); + assertTrue(pointOneKilometer.lessThan(oneHundredPointFiveMeters)); + assertFalse(oneHundredPointFiveMeters.lessThan(oneHundredMeters)); + } + + @Test + void equalHashCode() { + assertEquals(Distance.ofMeters(5d).hashCode(), Distance.ofMeters(5d).hashCode()); + assertNotEquals(Distance.ofMeters(5d).hashCode(), Double.valueOf(5d).hashCode()); + } +} From a51398a48fb4a23737eea0b220387eca8559688c Mon Sep 17 00:00:00 2001 From: JustCris Date: Tue, 3 Dec 2024 12:52:13 +0100 Subject: [PATCH 07/22] represent currentRangeMeters with integer type --- .../gtfs/datafetchers/RentalVehicleImpl.java | 6 ++--- .../gtfs/generated/GraphQLDataFetchers.java | 2 +- .../model/VehicleRentalVehicle.java | 16 +++++++++++-- .../transit/model/basic/Distance.java | 4 ++-- .../GbfsFreeVehicleStatusMapper.java | 4 +--- .../opentripplanner/apis/gtfs/schema.graphqls | 2 +- .../apis/gtfs/GraphQLIntegrationTest.java | 14 ++++++++--- .../TestFreeFloatingRentalVehicleBuilder.java | 20 ++++++++++------ .../gtfs/expectations/rental-vehicle.json | 2 +- .../expectations/vehicle-rentals-bybbox.json | 24 ++++++++++++++++++- .../queries/vehicle-rentals-bybbox.graphql | 2 ++ 11 files changed, 71 insertions(+), 25 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java index 4d1787219b4..2ae08e5e236 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java @@ -22,11 +22,9 @@ public DataFetcher currentFuelPercent() { } @Override - public DataFetcher currentRangeMeters() { + public DataFetcher currentRangeMeters() { return environment -> - getSource(environment).getCurrentRangeMeters() != null - ? getSource(environment).getCurrentRangeMeters().toMeters() - : null; + getSource(environment).getCurrentRangeMeters(); } @Override diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index b1d2f32ffda..34226365f91 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -899,7 +899,7 @@ public interface GraphQLRentalVehicle { public DataFetcher currentFuelPercent(); - public DataFetcher currentRangeMeters(); + public DataFetcher currentRangeMeters(); public DataFetcher id(); diff --git a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java index b8161ed8fe9..00d5b2bb87a 100644 --- a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java +++ b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java @@ -2,6 +2,7 @@ import java.time.Instant; import java.util.Set; +import javax.annotation.Nullable; import org.opentripplanner.framework.i18n.I18NString; import org.opentripplanner.street.model.RentalFormFactor; import org.opentripplanner.transit.model.basic.Distance; @@ -140,7 +141,18 @@ public Double getCurrentFuelPercent() { return currentFuelPercent; } - public Distance getCurrentRangeMeters() { - return currentRangeMeters; + public Integer getCurrentRangeMeters() { + if (this.currentRangeMeters == null) { + return null; + } + return this.currentRangeMeters.toMeters(); + } + + public void setCurrentRangeMeters(@Nullable Double currentRangeMeters) { + if (currentRangeMeters != null) { + this.currentRangeMeters = Distance.ofMeters(currentRangeMeters); + } else { + this.currentRangeMeters = null; + } } } diff --git a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java index 86335cbdb64..d0d34ce600e 100644 --- a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java +++ b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java @@ -24,8 +24,8 @@ public static Distance ofKilometers(double value) { } /** Returns the distance in meters */ - public double toMeters() { - return this.meters; + public int toMeters() { + return (int) Math.round(this.meters); } /** diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index 975ce4cebd1..d926b955dd4 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -54,9 +54,7 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { ? Instant.ofEpochSecond((long) (double) vehicle.getLastReported()) : null; rentalVehicle.currentFuelPercent = vehicle.getCurrentFuelPercent(); - Double currentRangeMeters = vehicle.getCurrentRangeMeters(); - rentalVehicle.currentRangeMeters = - currentRangeMeters != null ? Distance.ofMeters(currentRangeMeters) : null; + rentalVehicle.setCurrentRangeMeters(vehicle.getCurrentRangeMeters()); rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); GBFSRentalUris rentalUris = vehicle.getRentalUris(); if (rentalUris != null) { diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 3f4b8984f14..ed7e960be00 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -1877,7 +1877,7 @@ type RentalVehicle implements Node & PlaceInterface { "Fuel or battery power remaining in the vehicle. Expressed from 0 to 1." currentFuelPercent: Float "Range in meters that the vehicle can travel with the current charge or fuel." - currentRangeMeters: Float + currentRangeMeters: Int "Global object ID provided by Relay. This value can be used to refetch this object using **node** query." id: ID! "Latitude of the vehicle (WGS 84)" diff --git a/application/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java b/application/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java index 7e1bf24287a..d10c56aee7f 100644 --- a/application/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java +++ b/application/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java @@ -133,10 +133,17 @@ class GraphQLIntegrationTest { .withSystem("Network-1", "https://foo.bar") .build(); - private static final VehicleRentalVehicle RENTAL_VEHICLE = new TestFreeFloatingRentalVehicleBuilder() + private static final VehicleRentalVehicle RENTAL_VEHICLE_1 = new TestFreeFloatingRentalVehicleBuilder() .withSystem("Network-1", "https://foo.bar") .build(); + private static final VehicleRentalVehicle RENTAL_VEHICLE_2 = new TestFreeFloatingRentalVehicleBuilder() + .withSystem("Network-2", "https://foo.bar.baz") + .withNetwork("Network-2") + .withCurrentRangeMeters(null) + .withCurrentFuelPercent(null) + .build(); + static final Graph GRAPH = new Graph(); static final Instant ALERT_START_TIME = OffsetDateTime @@ -344,7 +351,8 @@ public Set findRoutes(StopLocation stop) { DefaultVehicleRentalService defaultVehicleRentalService = new DefaultVehicleRentalService(); defaultVehicleRentalService.addVehicleRentalStation(VEHICLE_RENTAL_STATION); - defaultVehicleRentalService.addVehicleRentalStation(RENTAL_VEHICLE); + defaultVehicleRentalService.addVehicleRentalStation(RENTAL_VEHICLE_1); + defaultVehicleRentalService.addVehicleRentalStation(RENTAL_VEHICLE_2); context = new GraphQLRequestContext( @@ -511,7 +519,7 @@ public List findClosestPlaces( return List.of( new PlaceAtDistance(stop, 0), new PlaceAtDistance(VEHICLE_RENTAL_STATION, 30), - new PlaceAtDistance(RENTAL_VEHICLE, 50) + new PlaceAtDistance(RENTAL_VEHICLE_1, 50) ); } }; diff --git a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java index 28d1a62503c..a79229c45bc 100644 --- a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java +++ b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java @@ -11,13 +11,14 @@ public class TestFreeFloatingRentalVehicleBuilder { public static final double DEFAULT_LATITUDE = 47.520; public static final double DEFAULT_LONGITUDE = 19.01; public static final double DEFAULT_CURRENT_FUEL_PERCENT = 0.5; - public static final double DEFAULT_CURRENT_RANGE_METERS = 5500; + public static final double DEFAULT_CURRENT_RANGE_METERS = 5500.7; private double latitude = DEFAULT_LATITUDE; private double longitude = DEFAULT_LONGITUDE; - private double currentFuelPercent = DEFAULT_CURRENT_FUEL_PERCENT; - private double currentRangeMeters = DEFAULT_CURRENT_RANGE_METERS; + private Double currentFuelPercent = DEFAULT_CURRENT_FUEL_PERCENT; + private Double currentRangeMeters = DEFAULT_CURRENT_RANGE_METERS; private VehicleRentalSystem system = null; + private String network = NETWORK_1; private RentalVehicleType vehicleType = RentalVehicleType.getDefaultType(NETWORK_1); @@ -35,16 +36,21 @@ public TestFreeFloatingRentalVehicleBuilder withLongitude(double longitude) { return this; } - public TestFreeFloatingRentalVehicleBuilder withCurrentFuelPercent(double currentFuelPercent) { + public TestFreeFloatingRentalVehicleBuilder withCurrentFuelPercent(Double currentFuelPercent) { this.currentFuelPercent = currentFuelPercent; return this; } - public TestFreeFloatingRentalVehicleBuilder withCurrentRangeMeters(double currentRangeMeters) { + public TestFreeFloatingRentalVehicleBuilder withCurrentRangeMeters(Double currentRangeMeters) { this.currentRangeMeters = currentRangeMeters; return this; } + public TestFreeFloatingRentalVehicleBuilder withNetwork(String network) { + this.network = network; + return this; + } + public TestFreeFloatingRentalVehicleBuilder withSystem(String id, String url) { this.system = new VehicleRentalSystem( @@ -94,14 +100,14 @@ private TestFreeFloatingRentalVehicleBuilder buildVehicleType(RentalFormFactor r public VehicleRentalVehicle build() { var vehicle = new VehicleRentalVehicle(); var stationName = "free-floating-" + vehicleType.formFactor.name().toLowerCase(); - vehicle.id = new FeedScopedId(NETWORK_1, stationName); + vehicle.id = new FeedScopedId(this.network, stationName); vehicle.name = new NonLocalizedString(stationName); vehicle.latitude = latitude; vehicle.longitude = longitude; vehicle.vehicleType = vehicleType; vehicle.system = system; vehicle.currentFuelPercent = currentFuelPercent; - vehicle.currentRangeMeters = Distance.ofMeters(currentRangeMeters); + vehicle.setCurrentRangeMeters(currentRangeMeters); return vehicle; } } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json index e8e532bedcc..f4070a0feff 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json @@ -17,7 +17,7 @@ "url": "https://foo.bar" }, "currentFuelPercent": 0.5, - "currentRangeMeters": 5500.0 + "currentRangeMeters": 5501 } } } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/vehicle-rentals-bybbox.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/vehicle-rentals-bybbox.json index d28e62f8d93..03d2a36e948 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/vehicle-rentals-bybbox.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/vehicle-rentals-bybbox.json @@ -76,7 +76,29 @@ "rentalNetwork": { "networkId": "Network-1", "url": "https://foo.bar" - } + }, + "currentFuelPercent": 0.5, + "currentRangeMeters": 5501 + }, + { + "__typename": "RentalVehicle", + "vehicleId": "Network-2:free-floating-bicycle", + "name": "free-floating-bicycle", + "allowPickupNow": true, + "lon": 19.01, + "lat": 47.52, + "rentalUris": null, + "operative": true, + "vehicleType": { + "formFactor": "BICYCLE", + "propulsionType": "HUMAN" + }, + "rentalNetwork": { + "networkId": "Network-2", + "url": "https://foo.bar.baz" + }, + "currentFuelPercent": null, + "currentRangeMeters": null } ] } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/vehicle-rentals-bybbox.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/vehicle-rentals-bybbox.graphql index 26209f427f9..adbe51299d3 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/vehicle-rentals-bybbox.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/vehicle-rentals-bybbox.graphql @@ -26,6 +26,8 @@ networkId url } + currentFuelPercent + currentRangeMeters } ... on VehicleRentalStation { stationId From 22a40a111688fdb626c91905d2c48e99995dd9fd Mon Sep 17 00:00:00 2001 From: JustCris Date: Tue, 3 Dec 2024 14:46:20 +0100 Subject: [PATCH 08/22] format RentalVehicleImpl file --- .../apis/gtfs/datafetchers/RentalVehicleImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java index 2ae08e5e236..2faf9d71280 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java @@ -23,8 +23,7 @@ public DataFetcher currentFuelPercent() { @Override public DataFetcher currentRangeMeters() { - return environment -> - getSource(environment).getCurrentRangeMeters(); + return environment -> getSource(environment).getCurrentRangeMeters(); } @Override From b0167fa3973b879551bbc46b0cdd9a40f945c12f Mon Sep 17 00:00:00 2001 From: JustCris Date: Tue, 3 Dec 2024 16:53:06 +0100 Subject: [PATCH 09/22] proper naming for static variables --- .../routing/core/DistanceTest.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java b/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java index 5ec561916d5..e990e111215 100644 --- a/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java +++ b/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java @@ -10,33 +10,33 @@ public class DistanceTest { - private static final Distance oneThousandFiveHundredMeters = Distance.ofMeters(1500d); - private static final Distance onePointFiveKilometers = Distance.ofKilometers(1.5d); - private static final Distance twoKilometers = Distance.ofKilometers(2d); - private static final Distance oneHundredMeters = Distance.ofMeters(100d); - private static final Distance pointOneKilometer = Distance.ofKilometers(0.1d); - private static final Distance oneHundredPointFiveMeters = Distance.ofMeters(100.5d); + private static final Distance ONE_THOUSAND_FIVE_HUNDRED_METERS = Distance.ofMeters(1500d); + private static final Distance ONE_POINT_FIVE_KILOMETERS = Distance.ofKilometers(1.5d); + private static final Distance TWO_KILOMETERS = Distance.ofKilometers(2d); + private static final Distance ONE_HUNDRED_METERS = Distance.ofMeters(100d); + private static final Distance POINT_ONE_KILOMETER = Distance.ofKilometers(0.1d); + private static final Distance ONE_HUNDRED_POINT_FIVE_METERS = Distance.ofMeters(100.5d); @Test void equals() { - assertEquals(oneThousandFiveHundredMeters, onePointFiveKilometers); - assertEquals(pointOneKilometer, oneHundredMeters); - assertNotEquals(oneHundredPointFiveMeters, oneHundredMeters); - assertNotEquals(twoKilometers, onePointFiveKilometers); + assertEquals(ONE_THOUSAND_FIVE_HUNDRED_METERS, ONE_POINT_FIVE_KILOMETERS); + assertEquals(POINT_ONE_KILOMETER, ONE_HUNDRED_METERS); + assertNotEquals(ONE_HUNDRED_POINT_FIVE_METERS, ONE_HUNDRED_METERS); + assertNotEquals(TWO_KILOMETERS, ONE_POINT_FIVE_KILOMETERS); } @Test void greaterThan() { - assertTrue(oneHundredPointFiveMeters.greaterThan(oneHundredMeters)); - assertTrue(twoKilometers.greaterThan(oneThousandFiveHundredMeters)); - assertFalse(oneThousandFiveHundredMeters.greaterThan(onePointFiveKilometers)); + assertTrue(ONE_HUNDRED_POINT_FIVE_METERS.greaterThan(ONE_HUNDRED_METERS)); + assertTrue(TWO_KILOMETERS.greaterThan(ONE_THOUSAND_FIVE_HUNDRED_METERS)); + assertFalse(ONE_THOUSAND_FIVE_HUNDRED_METERS.greaterThan(ONE_POINT_FIVE_KILOMETERS)); } @Test void lessThan() { - assertTrue(oneThousandFiveHundredMeters.lessThan(twoKilometers)); - assertTrue(pointOneKilometer.lessThan(oneHundredPointFiveMeters)); - assertFalse(oneHundredPointFiveMeters.lessThan(oneHundredMeters)); + assertTrue(ONE_THOUSAND_FIVE_HUNDRED_METERS.lessThan(TWO_KILOMETERS)); + assertTrue(POINT_ONE_KILOMETER.lessThan(ONE_HUNDRED_POINT_FIVE_METERS)); + assertFalse(ONE_HUNDRED_POINT_FIVE_METERS.lessThan(ONE_HUNDRED_METERS)); } @Test From a25e58a0fa890ed917652318f131a63812cbfaa0 Mon Sep 17 00:00:00 2001 From: JustCris Date: Wed, 4 Dec 2024 15:15:56 +0100 Subject: [PATCH 10/22] use Ratio scalar for currentFuelPercent --- .../resources/org/opentripplanner/apis/gtfs/schema.graphqls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index ed7e960be00..981b99295c5 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -1875,7 +1875,7 @@ type RentalVehicle implements Node & PlaceInterface { "If true, vehicle is currently available for renting." allowPickupNow: Boolean "Fuel or battery power remaining in the vehicle. Expressed from 0 to 1." - currentFuelPercent: Float + currentFuelPercent: Ratio "Range in meters that the vehicle can travel with the current charge or fuel." currentRangeMeters: Int "Global object ID provided by Relay. This value can be used to refetch this object using **node** query." From 5b94297d30998dcceedfbefd6e29dcbf4846d342 Mon Sep 17 00:00:00 2001 From: JustCris Date: Wed, 4 Dec 2024 15:37:22 +0100 Subject: [PATCH 11/22] rename currentRangeMeters to currentRange --- .../gtfs/datafetchers/RentalVehicleImpl.java | 2 +- .../transmodel/model/stop/RentalVehicleType.java | 4 +--- .../model/VehicleRentalVehicle.java | 16 ++++++++-------- .../datasources/GbfsFreeVehicleStatusMapper.java | 3 +-- .../TestFreeFloatingRentalVehicleBuilder.java | 3 +-- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java index 2faf9d71280..ed8d2ff20d0 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java @@ -23,7 +23,7 @@ public DataFetcher currentFuelPercent() { @Override public DataFetcher currentRangeMeters() { - return environment -> getSource(environment).getCurrentRangeMeters(); + return environment -> getSource(environment).getCurrentRange(); } @Override diff --git a/application/src/main/java/org/opentripplanner/apis/transmodel/model/stop/RentalVehicleType.java b/application/src/main/java/org/opentripplanner/apis/transmodel/model/stop/RentalVehicleType.java index e44639e09e7..9b78624b7ec 100644 --- a/application/src/main/java/org/opentripplanner/apis/transmodel/model/stop/RentalVehicleType.java +++ b/application/src/main/java/org/opentripplanner/apis/transmodel/model/stop/RentalVehicleType.java @@ -70,9 +70,7 @@ public static GraphQLObjectType create( .newFieldDefinition() .name("currentRangeMeters") .type(Scalars.GraphQLFloat) - .dataFetcher(environment -> - ((VehicleRentalVehicle) environment.getSource()).currentRangeMeters - ) + .dataFetcher(environment -> ((VehicleRentalVehicle) environment.getSource()).currentRange) .build() ) .build(); diff --git a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java index 00d5b2bb87a..23c07e31cf1 100644 --- a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java +++ b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java @@ -24,7 +24,7 @@ public class VehicleRentalVehicle implements VehicleRentalPlace { public boolean isReserved = false; public boolean isDisabled = false; public Instant lastReported; - public Distance currentRangeMeters; + public Distance currentRange; public VehicleRentalStation station; public String pricingPlanId; public Double currentFuelPercent; @@ -141,18 +141,18 @@ public Double getCurrentFuelPercent() { return currentFuelPercent; } - public Integer getCurrentRangeMeters() { - if (this.currentRangeMeters == null) { + public Integer getCurrentRange() { + if (this.currentRange == null) { return null; } - return this.currentRangeMeters.toMeters(); + return this.currentRange.toMeters(); } - public void setCurrentRangeMeters(@Nullable Double currentRangeMeters) { - if (currentRangeMeters != null) { - this.currentRangeMeters = Distance.ofMeters(currentRangeMeters); + public void setCurrentRange(@Nullable Double currentRange) { + if (currentRange != null) { + this.currentRange = Distance.ofMeters(currentRange); } else { - this.currentRangeMeters = null; + this.currentRange = null; } } } diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index d926b955dd4..2617b905b6a 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -13,7 +13,6 @@ import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; import org.opentripplanner.service.vehiclerental.model.VehicleRentalSystem; import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle; -import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.transit.model.framework.FeedScopedId; public class GbfsFreeVehicleStatusMapper { @@ -54,7 +53,7 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { ? Instant.ofEpochSecond((long) (double) vehicle.getLastReported()) : null; rentalVehicle.currentFuelPercent = vehicle.getCurrentFuelPercent(); - rentalVehicle.setCurrentRangeMeters(vehicle.getCurrentRangeMeters()); + rentalVehicle.setCurrentRange(vehicle.getCurrentRangeMeters()); rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); GBFSRentalUris rentalUris = vehicle.getRentalUris(); if (rentalUris != null) { diff --git a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java index a79229c45bc..16208d1f41e 100644 --- a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java +++ b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java @@ -2,7 +2,6 @@ import org.opentripplanner.framework.i18n.NonLocalizedString; import org.opentripplanner.street.model.RentalFormFactor; -import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.transit.model.framework.FeedScopedId; public class TestFreeFloatingRentalVehicleBuilder { @@ -107,7 +106,7 @@ public VehicleRentalVehicle build() { vehicle.vehicleType = vehicleType; vehicle.system = system; vehicle.currentFuelPercent = currentFuelPercent; - vehicle.setCurrentRangeMeters(currentRangeMeters); + vehicle.setCurrentRange(currentRangeMeters); return vehicle; } } From c8da0f4ca7a7371138564ad6db4fa525e10cf45e Mon Sep 17 00:00:00 2001 From: JustCris Date: Wed, 4 Dec 2024 15:52:08 +0100 Subject: [PATCH 12/22] move conversion of Distance to-from meters to the api and gbfs mapping --- .../apis/gtfs/datafetchers/RentalVehicleImpl.java | 5 ++++- .../vehiclerental/model/VehicleRentalVehicle.java | 15 ++------------- .../datasources/GbfsFreeVehicleStatusMapper.java | 6 +++++- .../TestFreeFloatingRentalVehicleBuilder.java | 4 +++- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java index ed8d2ff20d0..8f04a58b9c1 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java @@ -23,7 +23,10 @@ public DataFetcher currentFuelPercent() { @Override public DataFetcher currentRangeMeters() { - return environment -> getSource(environment).getCurrentRange(); + return environment -> + getSource(environment).getCurrentRange() != null + ? getSource(environment).getCurrentRange().toMeters() + : null; } @Override diff --git a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java index 23c07e31cf1..9c2f62e3785 100644 --- a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java +++ b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java @@ -141,18 +141,7 @@ public Double getCurrentFuelPercent() { return currentFuelPercent; } - public Integer getCurrentRange() { - if (this.currentRange == null) { - return null; - } - return this.currentRange.toMeters(); - } - - public void setCurrentRange(@Nullable Double currentRange) { - if (currentRange != null) { - this.currentRange = Distance.ofMeters(currentRange); - } else { - this.currentRange = null; - } + public Distance getCurrentRange() { + return this.currentRange; } } diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index 2617b905b6a..14833704309 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -13,6 +13,7 @@ import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; import org.opentripplanner.service.vehiclerental.model.VehicleRentalSystem; import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle; +import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.transit.model.framework.FeedScopedId; public class GbfsFreeVehicleStatusMapper { @@ -53,7 +54,10 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { ? Instant.ofEpochSecond((long) (double) vehicle.getLastReported()) : null; rentalVehicle.currentFuelPercent = vehicle.getCurrentFuelPercent(); - rentalVehicle.setCurrentRange(vehicle.getCurrentRangeMeters()); + rentalVehicle.currentRange = + vehicle.getCurrentRangeMeters() != null + ? Distance.ofMeters(vehicle.getCurrentRangeMeters()) + : null; rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); GBFSRentalUris rentalUris = vehicle.getRentalUris(); if (rentalUris != null) { diff --git a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java index 16208d1f41e..35e349f4fad 100644 --- a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java +++ b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java @@ -2,6 +2,7 @@ import org.opentripplanner.framework.i18n.NonLocalizedString; import org.opentripplanner.street.model.RentalFormFactor; +import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.transit.model.framework.FeedScopedId; public class TestFreeFloatingRentalVehicleBuilder { @@ -106,7 +107,8 @@ public VehicleRentalVehicle build() { vehicle.vehicleType = vehicleType; vehicle.system = system; vehicle.currentFuelPercent = currentFuelPercent; - vehicle.setCurrentRange(currentRangeMeters); + vehicle.currentRange = + currentRangeMeters != null ? Distance.ofMeters(currentRangeMeters) : null; return vehicle; } } From cd54bd1cbc92b37f15b42a55a5d0e4d524e8756a Mon Sep 17 00:00:00 2001 From: JustCris Date: Wed, 4 Dec 2024 17:03:56 +0100 Subject: [PATCH 13/22] remove unused code Distance class --- .../transit/model/basic/Distance.java | 14 -------------- .../routing/core/DistanceTest.java | 18 +----------------- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java index d0d34ce600e..05613f8e3b0 100644 --- a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java +++ b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java @@ -28,20 +28,6 @@ public int toMeters() { return (int) Math.round(this.meters); } - /** - * Is this distance greater than the one passed in - */ - public boolean greaterThan(Distance distance) { - return this.meters > distance.meters; - } - - /** - * Is this distance less than the one passed in - */ - public boolean lessThan(Distance distance) { - return this.meters < distance.meters; - } - @Override public boolean equals(Object other) { if (other instanceof Distance distance) { diff --git a/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java b/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java index e990e111215..16ee7e93565 100644 --- a/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java +++ b/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java @@ -1,9 +1,7 @@ package org.opentripplanner.routing.core; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.opentripplanner.transit.model.basic.Distance; @@ -26,21 +24,7 @@ void equals() { } @Test - void greaterThan() { - assertTrue(ONE_HUNDRED_POINT_FIVE_METERS.greaterThan(ONE_HUNDRED_METERS)); - assertTrue(TWO_KILOMETERS.greaterThan(ONE_THOUSAND_FIVE_HUNDRED_METERS)); - assertFalse(ONE_THOUSAND_FIVE_HUNDRED_METERS.greaterThan(ONE_POINT_FIVE_KILOMETERS)); - } - - @Test - void lessThan() { - assertTrue(ONE_THOUSAND_FIVE_HUNDRED_METERS.lessThan(TWO_KILOMETERS)); - assertTrue(POINT_ONE_KILOMETER.lessThan(ONE_HUNDRED_POINT_FIVE_METERS)); - assertFalse(ONE_HUNDRED_POINT_FIVE_METERS.lessThan(ONE_HUNDRED_METERS)); - } - - @Test - void equalHashCode() { + void equalsHashCode() { assertEquals(Distance.ofMeters(5d).hashCode(), Distance.ofMeters(5d).hashCode()); assertNotEquals(Distance.ofMeters(5d).hashCode(), Double.valueOf(5d).hashCode()); } From f2b9f145dfbe89d7bd78b33e99417d49ccfa30fb Mon Sep 17 00:00:00 2001 From: JustCris Date: Mon, 9 Dec 2024 11:34:11 +0100 Subject: [PATCH 14/22] group range and percent in fuel type --- .../gtfs/datafetchers/RentalVehicleImpl.java | 13 ++---- .../gtfs/generated/GraphQLDataFetchers.java | 12 ++++-- .../apis/gtfs/generated/graphql-codegen.yml | 1 + .../model/stop/RentalVehicleType.java | 4 +- .../model/RentalVehicleFuel.java | 43 +++++++++++++++++++ .../model/VehicleRentalVehicle.java | 13 ++---- .../GbfsFreeVehicleStatusMapper.java | 8 ++-- .../opentripplanner/apis/gtfs/schema.graphqls | 14 ++++-- .../TestFreeFloatingRentalVehicleBuilder.java | 32 +++++++------- .../gtfs/expectations/rental-vehicle.json | 6 ++- .../expectations/vehicle-rentals-bybbox.json | 12 ++++-- .../apis/gtfs/queries/rental-vehicle.graphql | 6 ++- .../queries/vehicle-rentals-bybbox.graphql | 6 ++- 13 files changed, 114 insertions(+), 56 deletions(-) create mode 100644 application/src/main/java/org/opentripplanner/service/vehiclerental/model/RentalVehicleFuel.java diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java index 8f04a58b9c1..5697aa15a5f 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/RentalVehicleImpl.java @@ -4,6 +4,7 @@ import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; +import org.opentripplanner.service.vehiclerental.model.RentalVehicleFuel; import org.opentripplanner.service.vehiclerental.model.RentalVehicleType; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; import org.opentripplanner.service.vehiclerental.model.VehicleRentalSystem; @@ -17,16 +18,8 @@ public DataFetcher allowPickupNow() { } @Override - public DataFetcher currentFuelPercent() { - return environment -> getSource(environment).getCurrentFuelPercent(); - } - - @Override - public DataFetcher currentRangeMeters() { - return environment -> - getSource(environment).getCurrentRange() != null - ? getSource(environment).getCurrentRange().toMeters() - : null; + public DataFetcher fuel() { + return environment -> getSource(environment).getFuel(); } @Override diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 34226365f91..091e0be59f1 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -58,6 +58,7 @@ import org.opentripplanner.service.vehicleparking.model.VehicleParkingSpaces; import org.opentripplanner.service.vehicleparking.model.VehicleParkingState; import org.opentripplanner.service.vehiclerental.model.RentalVehicleEntityCounts; +import org.opentripplanner.service.vehiclerental.model.RentalVehicleFuel; import org.opentripplanner.service.vehiclerental.model.RentalVehicleType; import org.opentripplanner.service.vehiclerental.model.RentalVehicleTypeCount; import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace; @@ -897,9 +898,7 @@ public interface GraphQLRentalPlace extends TypeResolver {} public interface GraphQLRentalVehicle { public DataFetcher allowPickupNow(); - public DataFetcher currentFuelPercent(); - - public DataFetcher currentRangeMeters(); + public DataFetcher fuel(); public DataFetcher id(); @@ -928,6 +927,13 @@ public interface GraphQLRentalVehicleEntityCounts { public DataFetcher total(); } + /** Rental vehicle fuel represent the current status of the battery or fuel of a rental vehicle */ + public interface GraphQLRentalVehicleFuel { + public DataFetcher percent(); + + public DataFetcher range(); + } + public interface GraphQLRentalVehicleType { public DataFetcher formFactor(); diff --git a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index a9bb87a6ea5..3272efa894f 100644 --- a/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/application/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -134,4 +134,5 @@ config: CallRealTime: org.opentripplanner.apis.gtfs.model.CallRealTime#CallRealTime RentalPlace: org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace#VehicleRentalPlace CallSchedule: org.opentripplanner.apis.gtfs.model.CallSchedule#CallSchedule + RentalVehicleFuel: org.opentripplanner.service.vehiclerental.model.RentalVehicleFuel#RentalVehicleFuel diff --git a/application/src/main/java/org/opentripplanner/apis/transmodel/model/stop/RentalVehicleType.java b/application/src/main/java/org/opentripplanner/apis/transmodel/model/stop/RentalVehicleType.java index 9b78624b7ec..8694fe0d95d 100644 --- a/application/src/main/java/org/opentripplanner/apis/transmodel/model/stop/RentalVehicleType.java +++ b/application/src/main/java/org/opentripplanner/apis/transmodel/model/stop/RentalVehicleType.java @@ -70,7 +70,9 @@ public static GraphQLObjectType create( .newFieldDefinition() .name("currentRangeMeters") .type(Scalars.GraphQLFloat) - .dataFetcher(environment -> ((VehicleRentalVehicle) environment.getSource()).currentRange) + .dataFetcher(environment -> + ((VehicleRentalVehicle) environment.getSource()).getFuel().getRange() + ) .build() ) .build(); diff --git a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/RentalVehicleFuel.java b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/RentalVehicleFuel.java new file mode 100644 index 00000000000..b38f1ce0913 --- /dev/null +++ b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/RentalVehicleFuel.java @@ -0,0 +1,43 @@ +package org.opentripplanner.service.vehiclerental.model; + +import javax.annotation.Nullable; +import org.opentripplanner.transit.model.basic.Distance; + +/** + * Contains information about the current battery or fuel status. + * See the GBFS + * vehicle_status specification for more details. + */ +public class RentalVehicleFuel { + + /** + * Current fuel percentage, expressed from 0 to 1. + *

+ * May be {@code null}. + */ + @Nullable + public final Double percent; + + /** + * Distance that the vehicle can travel with the current charge or fuel. + *

+ * May be {@code null}. + */ + @Nullable + public final Distance range; + + public RentalVehicleFuel(@Nullable Double fuelPercent, @Nullable Distance range) { + this.percent = fuelPercent; + this.range = range; + } + + @Nullable + public Double getPercent() { + return percent; + } + + @Nullable + public Integer getRange() { + return this.range != null ? this.range.toMeters() : null; + } +} diff --git a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java index 9c2f62e3785..446711bad36 100644 --- a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java +++ b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/VehicleRentalVehicle.java @@ -2,10 +2,8 @@ import java.time.Instant; import java.util.Set; -import javax.annotation.Nullable; import org.opentripplanner.framework.i18n.I18NString; import org.opentripplanner.street.model.RentalFormFactor; -import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.transit.model.framework.FeedScopedId; /** @@ -24,10 +22,9 @@ public class VehicleRentalVehicle implements VehicleRentalPlace { public boolean isReserved = false; public boolean isDisabled = false; public Instant lastReported; - public Distance currentRange; public VehicleRentalStation station; public String pricingPlanId; - public Double currentFuelPercent; + public RentalVehicleFuel fuel; @Override public FeedScopedId getId() { @@ -137,11 +134,7 @@ public VehicleRentalSystem getVehicleRentalSystem() { return system; } - public Double getCurrentFuelPercent() { - return currentFuelPercent; - } - - public Distance getCurrentRange() { - return this.currentRange; + public RentalVehicleFuel getFuel() { + return fuel; } } diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index 14833704309..11efe00cd8a 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -9,6 +9,7 @@ import org.mobilitydata.gbfs.v2_3.free_bike_status.GBFSBike; import org.mobilitydata.gbfs.v2_3.free_bike_status.GBFSRentalUris; import org.opentripplanner.framework.i18n.NonLocalizedString; +import org.opentripplanner.service.vehiclerental.model.RentalVehicleFuel; import org.opentripplanner.service.vehiclerental.model.RentalVehicleType; import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris; import org.opentripplanner.service.vehiclerental.model.VehicleRentalSystem; @@ -53,11 +54,12 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { vehicle.getLastReported() != null ? Instant.ofEpochSecond((long) (double) vehicle.getLastReported()) : null; - rentalVehicle.currentFuelPercent = vehicle.getCurrentFuelPercent(); - rentalVehicle.currentRange = + RentalVehicleFuel fuel = new RentalVehicleFuel( + vehicle.getCurrentFuelPercent(), vehicle.getCurrentRangeMeters() != null ? Distance.ofMeters(vehicle.getCurrentRangeMeters()) - : null; + : null + ); rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); GBFSRentalUris rentalUris = vehicle.getRentalUris(); if (rentalUris != null) { diff --git a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 981b99295c5..8825f0fbf54 100644 --- a/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -1874,10 +1874,8 @@ type RealTimeEstimate { type RentalVehicle implements Node & PlaceInterface { "If true, vehicle is currently available for renting." allowPickupNow: Boolean - "Fuel or battery power remaining in the vehicle. Expressed from 0 to 1." - currentFuelPercent: Ratio - "Range in meters that the vehicle can travel with the current charge or fuel." - currentRangeMeters: Int + "Fuel or battery status of the rental vehicle" + fuel: RentalVehicleFuel "Global object ID provided by Relay. This value can be used to refetch this object using **node** query." id: ID! "Latitude of the vehicle (WGS 84)" @@ -1907,6 +1905,14 @@ type RentalVehicleEntityCounts { total: Int! } +"Rental vehicle fuel represent the current status of the battery or fuel of a rental vehicle" +type RentalVehicleFuel { + "Fuel or battery power remaining in the vehicle. Expressed from 0 to 1." + percent: Ratio + "Range in meters that the vehicle can travel with the current charge or fuel." + range: Int +} + type RentalVehicleType { "The vehicle's general form factor" formFactor: FormFactor diff --git a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java index 35e349f4fad..845e8faed68 100644 --- a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java +++ b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java @@ -85,18 +85,6 @@ public TestFreeFloatingRentalVehicleBuilder withVehicleCar() { return buildVehicleType(RentalFormFactor.CAR); } - private TestFreeFloatingRentalVehicleBuilder buildVehicleType(RentalFormFactor rentalFormFactor) { - this.vehicleType = - new RentalVehicleType( - new FeedScopedId(TestFreeFloatingRentalVehicleBuilder.NETWORK_1, rentalFormFactor.name()), - rentalFormFactor.name(), - rentalFormFactor, - RentalVehicleType.PropulsionType.ELECTRIC, - 100000d - ); - return this; - } - public VehicleRentalVehicle build() { var vehicle = new VehicleRentalVehicle(); var stationName = "free-floating-" + vehicleType.formFactor.name().toLowerCase(); @@ -106,9 +94,23 @@ public VehicleRentalVehicle build() { vehicle.longitude = longitude; vehicle.vehicleType = vehicleType; vehicle.system = system; - vehicle.currentFuelPercent = currentFuelPercent; - vehicle.currentRange = - currentRangeMeters != null ? Distance.ofMeters(currentRangeMeters) : null; + vehicle.fuel = + new RentalVehicleFuel( + currentFuelPercent, + currentRangeMeters != null ? Distance.ofMeters(currentRangeMeters) : null + ); return vehicle; } + + private TestFreeFloatingRentalVehicleBuilder buildVehicleType(RentalFormFactor rentalFormFactor) { + this.vehicleType = + new RentalVehicleType( + new FeedScopedId(TestFreeFloatingRentalVehicleBuilder.NETWORK_1, rentalFormFactor.name()), + rentalFormFactor.name(), + rentalFormFactor, + RentalVehicleType.PropulsionType.ELECTRIC, + 100000d + ); + return this; + } } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json index f4070a0feff..7d739570a9d 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/rental-vehicle.json @@ -16,8 +16,10 @@ "networkId": "Network-1", "url": "https://foo.bar" }, - "currentFuelPercent": 0.5, - "currentRangeMeters": 5501 + "fuel": { + "percent": 0.5, + "range": 5501 + } } } } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/vehicle-rentals-bybbox.json b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/vehicle-rentals-bybbox.json index 03d2a36e948..10b7924d745 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/vehicle-rentals-bybbox.json +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/expectations/vehicle-rentals-bybbox.json @@ -77,8 +77,10 @@ "networkId": "Network-1", "url": "https://foo.bar" }, - "currentFuelPercent": 0.5, - "currentRangeMeters": 5501 + "fuel": { + "percent": 0.5, + "range": 5501 + } }, { "__typename": "RentalVehicle", @@ -97,8 +99,10 @@ "networkId": "Network-2", "url": "https://foo.bar.baz" }, - "currentFuelPercent": null, - "currentRangeMeters": null + "fuel": { + "percent": null, + "range": null + } } ] } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql index 5fd8da8c5fd..8f32632abc0 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/rental-vehicle.graphql @@ -19,7 +19,9 @@ networkId url } - currentFuelPercent - currentRangeMeters + fuel { + percent + range + } } } diff --git a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/vehicle-rentals-bybbox.graphql b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/vehicle-rentals-bybbox.graphql index adbe51299d3..55c71954692 100644 --- a/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/vehicle-rentals-bybbox.graphql +++ b/application/src/test/resources/org/opentripplanner/apis/gtfs/queries/vehicle-rentals-bybbox.graphql @@ -26,8 +26,10 @@ networkId url } - currentFuelPercent - currentRangeMeters + fuel { + percent + range + } } ... on VehicleRentalStation { stationId From 57732a04f6fb08c71f4f72d7eaf850f2a46a665f Mon Sep 17 00:00:00 2001 From: JustCris Date: Mon, 9 Dec 2024 14:51:10 +0100 Subject: [PATCH 15/22] log warn if fuelPercent is invalid --- .../GbfsFreeVehicleStatusMapper.java | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index 11efe00cd8a..8ab3740542f 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -2,12 +2,14 @@ import static java.util.Objects.requireNonNullElse; +import graphql.schema.CoercingParseValueException; import java.time.Instant; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; import org.mobilitydata.gbfs.v2_3.free_bike_status.GBFSBike; import org.mobilitydata.gbfs.v2_3.free_bike_status.GBFSRentalUris; +import org.opentripplanner.apis.gtfs.GraphQLScalars; import org.opentripplanner.framework.i18n.NonLocalizedString; import org.opentripplanner.service.vehiclerental.model.RentalVehicleFuel; import org.opentripplanner.service.vehiclerental.model.RentalVehicleType; @@ -16,9 +18,13 @@ import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle; import org.opentripplanner.transit.model.basic.Distance; import org.opentripplanner.transit.model.framework.FeedScopedId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class GbfsFreeVehicleStatusMapper { + private static final Logger LOG = LoggerFactory.getLogger(GbfsFreeVehicleStatusMapper.class); + private final VehicleRentalSystem system; private final Map vehicleTypes; @@ -54,12 +60,28 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { vehicle.getLastReported() != null ? Instant.ofEpochSecond((long) (double) vehicle.getLastReported()) : null; - RentalVehicleFuel fuel = new RentalVehicleFuel( - vehicle.getCurrentFuelPercent(), - vehicle.getCurrentRangeMeters() != null - ? Distance.ofMeters(vehicle.getCurrentRangeMeters()) - : null - ); + Double fuelPercent = null; + if (vehicle.getCurrentFuelPercent() != null) { + try { + fuelPercent = + (Double) GraphQLScalars.RATIO_SCALAR + .getCoercing() + .parseValue(vehicle.getCurrentFuelPercent()); + } catch (CoercingParseValueException e) { + LOG.warn( + "Current fuel percent: {} - {}", + vehicle.getCurrentFuelPercent(), + e.getMessage() + ); + } + } + rentalVehicle.fuel = + new RentalVehicleFuel( + fuelPercent, + vehicle.getCurrentRangeMeters() != null + ? Distance.ofMeters(vehicle.getCurrentRangeMeters()) + : null + ); rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); GBFSRentalUris rentalUris = vehicle.getRentalUris(); if (rentalUris != null) { From 86f88a6a423e74704a53e3fa62b6094e420561c9 Mon Sep 17 00:00:00 2001 From: JustCris Date: Wed, 11 Dec 2024 18:16:46 +0100 Subject: [PATCH 16/22] check currentRangeMeters validity in free rental vehicle --- .../transit/model/basic/Distance.java | 16 ++++++++++++++-- .../GbfsFreeVehicleStatusMapper.java | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java index 05613f8e3b0..d0df42bb253 100644 --- a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java +++ b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java @@ -9,17 +9,29 @@ public class Distance { private final double meters; /** Returns a Distance object representing the given number of meters */ - public Distance(double value) { - this.meters = value; + public Distance(double distanceInMeters) { + if (distanceInMeters < 0) { + throw new IllegalArgumentException("Distance cannot be negative"); + } + + this.meters = distanceInMeters; } /** Returns a Distance object representing the given number of meters */ public static Distance ofMeters(double value) { + if (value < 0) { + throw new IllegalArgumentException("Distance cannot be negative"); + } + return new Distance(value); } /** Returns a Distance object representing the given number of kilometers */ public static Distance ofKilometers(double value) { + if (value < 0) { + throw new IllegalArgumentException("Distance cannot be negative"); + } + return new Distance(value * METERS_PER_KM); } diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index 8ab3740542f..d5620bff52f 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -75,12 +75,23 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { ); } } + Distance rangeMeters = null; + try { + rangeMeters = vehicle.getCurrentRangeMeters() != null + ? Distance.ofMeters(vehicle.getCurrentRangeMeters()) + : null; + } catch (IllegalArgumentException e) { + LOG.warn(e.getMessage()); + // if the propulsion type has an engine current_range_meters is required + if (vehicle.getVehicleTypeId() != null + && vehicleTypes.get(vehicle.getVehicleTypeId()).propulsionType != RentalVehicleType.PropulsionType.HUMAN) { + return null; + } + } rentalVehicle.fuel = new RentalVehicleFuel( fuelPercent, - vehicle.getCurrentRangeMeters() != null - ? Distance.ofMeters(vehicle.getCurrentRangeMeters()) - : null + rangeMeters ); rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); GBFSRentalUris rentalUris = vehicle.getRentalUris(); From 2152235471dd10b58129b859b0e0cfaa812389c9 Mon Sep 17 00:00:00 2001 From: JustCris Date: Wed, 11 Dec 2024 19:19:46 +0100 Subject: [PATCH 17/22] Ratio class --- .../transit/model/basic/Distance.java | 2 +- .../transit/model/basic/Ratio.java | 34 +++++++++++++++ .../routing/core/DistanceTest.java | 2 +- .../routing/core/RatioTest.java | 41 +++++++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java create mode 100644 application/src/test/java/org/opentripplanner/routing/core/RatioTest.java diff --git a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java index d0df42bb253..0b8061190be 100644 --- a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java +++ b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java @@ -51,7 +51,7 @@ public boolean equals(Object other) { @Override public int hashCode() { - return Objects.hash(meters, 31); + return Objects.hash(meters, "Distance"); } @Override diff --git a/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java b/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java new file mode 100644 index 00000000000..57276753e9d --- /dev/null +++ b/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java @@ -0,0 +1,34 @@ +package org.opentripplanner.transit.model.basic; + +import java.util.Objects; + +public class Ratio { + public final Double ratio; + + public Ratio(Double ratio) { + if (ratio < 0d || ratio > 1d) { + throw new IllegalArgumentException("Ratio must be in range [0,1]"); + } + + this.ratio = ratio; + } + + @Override + public boolean equals(Object other) { + if (other instanceof Ratio ratio) { + return ratio.ratio == this.ratio; + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hash(this.ratio, "Ratio"); + } + + @Override + public String toString() { + return this.ratio.toString(); + } +} diff --git a/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java b/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java index 16ee7e93565..2543eae70cd 100644 --- a/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java +++ b/application/src/test/java/org/opentripplanner/routing/core/DistanceTest.java @@ -24,7 +24,7 @@ void equals() { } @Test - void equalsHashCode() { + void testHashCode() { assertEquals(Distance.ofMeters(5d).hashCode(), Distance.ofMeters(5d).hashCode()); assertNotEquals(Distance.ofMeters(5d).hashCode(), Double.valueOf(5d).hashCode()); } diff --git a/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java b/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java new file mode 100644 index 00000000000..c434c4d54e7 --- /dev/null +++ b/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java @@ -0,0 +1,41 @@ +package org.opentripplanner.routing.core; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; +import org.opentripplanner.transit.model.basic.Ratio; + +public class RatioTest { + private static final Double HALF = 0.5d; + private static final Double ZERO = 0d; + private static final Double ONE = 1d; + private static final Double TOO_HIGH = 1.1d; + private static final Double TOO_LOW = -1.1d; + + @Test + void validRatios() { + assertDoesNotThrow(() -> new Ratio(HALF)); + assertDoesNotThrow(() -> new Ratio(ZERO)); + assertDoesNotThrow(() -> new Ratio(ONE)); + } + + @Test + void invalidRatios() { + assertThrows(IllegalArgumentException.class ,() -> new Ratio(TOO_HIGH)); + assertThrows(IllegalArgumentException.class ,() -> new Ratio(TOO_LOW)); + } + + @Test + void testHashCode() { + Ratio half = new Ratio(HALF); + + Ratio half2 = new Ratio(HALF); + assertEquals(half.hashCode(), half2.hashCode()); + + Double halfDouble = 2d; + assertNotEquals(half.hashCode(), halfDouble); + } +} From 9d8411b8e9e2c17f83febc51d09f80eec8bb5be4 Mon Sep 17 00:00:00 2001 From: JustCris Date: Tue, 17 Dec 2024 12:33:47 +0100 Subject: [PATCH 18/22] Ratio class for fuel percent validation --- .../model/RentalVehicleFuel.java | 7 +-- .../transit/model/basic/Distance.java | 2 +- .../transit/model/basic/Ratio.java | 2 +- .../GbfsFreeVehicleStatusMapper.java | 52 +++++++++---------- .../routing/core/RatioTest.java | 6 +-- .../TestFreeFloatingRentalVehicleBuilder.java | 14 +++-- 6 files changed, 46 insertions(+), 37 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/RentalVehicleFuel.java b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/RentalVehicleFuel.java index b38f1ce0913..2e24613f49d 100644 --- a/application/src/main/java/org/opentripplanner/service/vehiclerental/model/RentalVehicleFuel.java +++ b/application/src/main/java/org/opentripplanner/service/vehiclerental/model/RentalVehicleFuel.java @@ -2,6 +2,7 @@ import javax.annotation.Nullable; import org.opentripplanner.transit.model.basic.Distance; +import org.opentripplanner.transit.model.basic.Ratio; /** * Contains information about the current battery or fuel status. @@ -16,7 +17,7 @@ public class RentalVehicleFuel { * May be {@code null}. */ @Nullable - public final Double percent; + public final Ratio percent; /** * Distance that the vehicle can travel with the current charge or fuel. @@ -26,14 +27,14 @@ public class RentalVehicleFuel { @Nullable public final Distance range; - public RentalVehicleFuel(@Nullable Double fuelPercent, @Nullable Distance range) { + public RentalVehicleFuel(@Nullable Ratio fuelPercent, @Nullable Distance range) { this.percent = fuelPercent; this.range = range; } @Nullable public Double getPercent() { - return percent; + return this.percent != null ? this.percent.ratio : null; } @Nullable diff --git a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java index 0b8061190be..fef694ec023 100644 --- a/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java +++ b/application/src/main/java/org/opentripplanner/transit/model/basic/Distance.java @@ -18,7 +18,7 @@ public Distance(double distanceInMeters) { } /** Returns a Distance object representing the given number of meters */ - public static Distance ofMeters(double value) { + public static Distance ofMeters(double value) throws IllegalArgumentException { if (value < 0) { throw new IllegalArgumentException("Distance cannot be negative"); } diff --git a/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java b/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java index 57276753e9d..c93ece2a477 100644 --- a/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java +++ b/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java @@ -5,7 +5,7 @@ public class Ratio { public final Double ratio; - public Ratio(Double ratio) { + public Ratio(Double ratio) throws IllegalArgumentException { if (ratio < 0d || ratio > 1d) { throw new IllegalArgumentException("Ratio must be in range [0,1]"); } diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index d5620bff52f..00e99030c45 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -17,6 +17,7 @@ import org.opentripplanner.service.vehiclerental.model.VehicleRentalSystem; import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle; import org.opentripplanner.transit.model.basic.Distance; +import org.opentripplanner.transit.model.basic.Ratio; import org.opentripplanner.transit.model.framework.FeedScopedId; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,39 +61,38 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { vehicle.getLastReported() != null ? Instant.ofEpochSecond((long) (double) vehicle.getLastReported()) : null; - Double fuelPercent = null; - if (vehicle.getCurrentFuelPercent() != null) { - try { - fuelPercent = - (Double) GraphQLScalars.RATIO_SCALAR - .getCoercing() - .parseValue(vehicle.getCurrentFuelPercent()); - } catch (CoercingParseValueException e) { - LOG.warn( - "Current fuel percent: {} - {}", - vehicle.getCurrentFuelPercent(), - e.getMessage() - ); - } - } + Ratio fuelPercent = null; + try { + fuelPercent = new Ratio(vehicle.getCurrentFuelPercent()); + } catch (IllegalArgumentException e) { + LOG.warn( + "Current fuel percent value not valid: {} - {}", + vehicle.getCurrentFuelPercent(), + e.getMessage() + ); + } catch (NullPointerException e) {} Distance rangeMeters = null; try { - rangeMeters = vehicle.getCurrentRangeMeters() != null - ? Distance.ofMeters(vehicle.getCurrentRangeMeters()) - : null; + rangeMeters = + vehicle.getCurrentRangeMeters() != null + ? Distance.ofMeters(vehicle.getCurrentRangeMeters()) + : null; } catch (IllegalArgumentException e) { - LOG.warn(e.getMessage()); + LOG.warn( + "Current range meter value not valid: {} - {}", + vehicle.getCurrentRangeMeters(), + e.getMessage() + ); // if the propulsion type has an engine current_range_meters is required - if (vehicle.getVehicleTypeId() != null - && vehicleTypes.get(vehicle.getVehicleTypeId()).propulsionType != RentalVehicleType.PropulsionType.HUMAN) { + if ( + vehicle.getVehicleTypeId() != null && + vehicleTypes.get(vehicle.getVehicleTypeId()).propulsionType != + RentalVehicleType.PropulsionType.HUMAN + ) { return null; } } - rentalVehicle.fuel = - new RentalVehicleFuel( - fuelPercent, - rangeMeters - ); + rentalVehicle.fuel = new RentalVehicleFuel(fuelPercent, rangeMeters); rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); GBFSRentalUris rentalUris = vehicle.getRentalUris(); if (rentalUris != null) { diff --git a/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java b/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java index c434c4d54e7..f65b00e0e78 100644 --- a/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java +++ b/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java @@ -1,7 +1,7 @@ package org.opentripplanner.routing.core; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -24,8 +24,8 @@ void validRatios() { @Test void invalidRatios() { - assertThrows(IllegalArgumentException.class ,() -> new Ratio(TOO_HIGH)); - assertThrows(IllegalArgumentException.class ,() -> new Ratio(TOO_LOW)); + assertThrows(IllegalArgumentException.class, () -> new Ratio(TOO_HIGH)); + assertThrows(IllegalArgumentException.class, () -> new Ratio(TOO_LOW)); } @Test diff --git a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java index 845e8faed68..85dd57bfc1d 100644 --- a/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java +++ b/application/src/test/java/org/opentripplanner/service/vehiclerental/model/TestFreeFloatingRentalVehicleBuilder.java @@ -1,8 +1,10 @@ package org.opentripplanner.service.vehiclerental.model; +import javax.annotation.Nullable; import org.opentripplanner.framework.i18n.NonLocalizedString; import org.opentripplanner.street.model.RentalFormFactor; import org.opentripplanner.transit.model.basic.Distance; +import org.opentripplanner.transit.model.basic.Ratio; import org.opentripplanner.transit.model.framework.FeedScopedId; public class TestFreeFloatingRentalVehicleBuilder { @@ -15,7 +17,7 @@ public class TestFreeFloatingRentalVehicleBuilder { private double latitude = DEFAULT_LATITUDE; private double longitude = DEFAULT_LONGITUDE; - private Double currentFuelPercent = DEFAULT_CURRENT_FUEL_PERCENT; + private Ratio currentFuelPercent = new Ratio(DEFAULT_CURRENT_FUEL_PERCENT); private Double currentRangeMeters = DEFAULT_CURRENT_RANGE_METERS; private VehicleRentalSystem system = null; private String network = NETWORK_1; @@ -36,8 +38,14 @@ public TestFreeFloatingRentalVehicleBuilder withLongitude(double longitude) { return this; } - public TestFreeFloatingRentalVehicleBuilder withCurrentFuelPercent(Double currentFuelPercent) { - this.currentFuelPercent = currentFuelPercent; + public TestFreeFloatingRentalVehicleBuilder withCurrentFuelPercent( + @Nullable Double currentFuelPercent + ) { + if (currentFuelPercent == null) { + this.currentFuelPercent = null; + } else { + this.currentFuelPercent = new Ratio(currentFuelPercent); + } return this; } From c9c3a666fab682bd53a4470b841b1c53f88fa30b Mon Sep 17 00:00:00 2001 From: JustCris Date: Tue, 17 Dec 2024 14:03:53 +0100 Subject: [PATCH 19/22] Ratio class and test format --- .../main/java/org/opentripplanner/transit/model/basic/Ratio.java | 1 + .../test/java/org/opentripplanner/routing/core/RatioTest.java | 1 + 2 files changed, 2 insertions(+) diff --git a/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java b/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java index c93ece2a477..0c980be6eee 100644 --- a/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java +++ b/application/src/main/java/org/opentripplanner/transit/model/basic/Ratio.java @@ -3,6 +3,7 @@ import java.util.Objects; public class Ratio { + public final Double ratio; public Ratio(Double ratio) throws IllegalArgumentException { diff --git a/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java b/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java index f65b00e0e78..4195fc5c5c0 100644 --- a/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java +++ b/application/src/test/java/org/opentripplanner/routing/core/RatioTest.java @@ -9,6 +9,7 @@ import org.opentripplanner.transit.model.basic.Ratio; public class RatioTest { + private static final Double HALF = 0.5d; private static final Double ZERO = 0d; private static final Double ONE = 1d; From 086effd29d11515b2aef2d9cd73f48f9514e9593 Mon Sep 17 00:00:00 2001 From: JustCris Date: Tue, 17 Dec 2024 14:21:52 +0100 Subject: [PATCH 20/22] fix check when range is required --- .../datasources/GbfsFreeVehicleStatusMapper.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index 00e99030c45..44bcee84580 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -83,14 +83,12 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { vehicle.getCurrentRangeMeters(), e.getMessage() ); - // if the propulsion type has an engine current_range_meters is required - if ( - vehicle.getVehicleTypeId() != null && - vehicleTypes.get(vehicle.getVehicleTypeId()).propulsionType != - RentalVehicleType.PropulsionType.HUMAN - ) { - return null; - } + } + // if the propulsion type has an engine current_range_meters is required + if (vehicle.getVehicleTypeId() != null + && vehicleTypes.get(vehicle.getVehicleTypeId()).propulsionType != RentalVehicleType.PropulsionType.HUMAN + && rangeMeters == null) { + return null; } rentalVehicle.fuel = new RentalVehicleFuel(fuelPercent, rangeMeters); rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); From ee50eee3f9e0c93616b6a039d3d0d9c2ecc236c3 Mon Sep 17 00:00:00 2001 From: JustCris Date: Tue, 17 Dec 2024 14:28:36 +0100 Subject: [PATCH 21/22] format GbfsFreeVehicleStatusMapper --- .../datasources/GbfsFreeVehicleStatusMapper.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index 44bcee84580..1265583df13 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -85,9 +85,12 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { ); } // if the propulsion type has an engine current_range_meters is required - if (vehicle.getVehicleTypeId() != null - && vehicleTypes.get(vehicle.getVehicleTypeId()).propulsionType != RentalVehicleType.PropulsionType.HUMAN - && rangeMeters == null) { + if ( + vehicle.getVehicleTypeId() != null && + vehicleTypes.get(vehicle.getVehicleTypeId()).propulsionType != + RentalVehicleType.PropulsionType.HUMAN && + rangeMeters == null + ) { return null; } rentalVehicle.fuel = new RentalVehicleFuel(fuelPercent, rangeMeters); From 284133a7742531b0fb785f001d56d5a8d7fcb0fb Mon Sep 17 00:00:00 2001 From: JustCris Date: Tue, 17 Dec 2024 14:44:49 +0100 Subject: [PATCH 22/22] add range to scooter in GbfsFreeVehicleStatusMapperTest --- .../datasources/GbfsFreeVehicleStatusMapper.java | 3 +-- .../datasources/GbfsFreeVehicleStatusMapperTest.java | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java index 1265583df13..f2fd9315dd3 100644 --- a/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java +++ b/application/src/main/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapper.java @@ -2,14 +2,12 @@ import static java.util.Objects.requireNonNullElse; -import graphql.schema.CoercingParseValueException; import java.time.Instant; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; import org.mobilitydata.gbfs.v2_3.free_bike_status.GBFSBike; import org.mobilitydata.gbfs.v2_3.free_bike_status.GBFSRentalUris; -import org.opentripplanner.apis.gtfs.GraphQLScalars; import org.opentripplanner.framework.i18n.NonLocalizedString; import org.opentripplanner.service.vehiclerental.model.RentalVehicleFuel; import org.opentripplanner.service.vehiclerental.model.RentalVehicleType; @@ -87,6 +85,7 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { // if the propulsion type has an engine current_range_meters is required if ( vehicle.getVehicleTypeId() != null && + vehicleTypes.get(vehicle.getVehicleTypeId()) != null && vehicleTypes.get(vehicle.getVehicleTypeId()).propulsionType != RentalVehicleType.PropulsionType.HUMAN && rangeMeters == null diff --git a/application/src/test/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapperTest.java b/application/src/test/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapperTest.java index 02295ce09e9..79322d325fc 100644 --- a/application/src/test/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapperTest.java +++ b/application/src/test/java/org/opentripplanner/updater/vehicle_rental/datasources/GbfsFreeVehicleStatusMapperTest.java @@ -37,7 +37,7 @@ class GbfsFreeVehicleStatusMapperTest { new FeedScopedId("1", "scooter"), "Scooter", RentalFormFactor.SCOOTER, - null, + RentalVehicleType.PropulsionType.COMBUSTION, null ) ) @@ -62,7 +62,6 @@ void withDefaultType() { bike.setLon(1d); bike.setVehicleTypeId("bike"); var mapped = MAPPER.mapFreeVehicleStatus(bike); - assertEquals("Default vehicle type", mapped.name.toString()); } @@ -73,6 +72,7 @@ void withType() { bike.setLat(1d); bike.setLon(1d); bike.setVehicleTypeId("scooter"); + bike.setCurrentRangeMeters(2000d); var mapped = MAPPER.mapFreeVehicleStatus(bike); assertEquals("Scooter", mapped.name.toString());