-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add currentFuelPercent and currentRangeMeters to RentalVehichle in the GTFS GraphQL API #6272
base: dev-2.x
Are you sure you want to change the base?
Changes from all commits
f0ca862
4e13710
644f784
062a907
7d12fcd
95cdf38
a51398a
22a40a1
b0167fa
a25e58a
5b94297
c8da0f4
cd54bd1
f2b9f14
57732a0
86f88a6
2152235
9d8411b
c9c3a66
086effd
ee50eee
284133a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package org.opentripplanner.service.vehiclerental.model; | ||
|
||
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. | ||
* See the <a href="https://github.com/MobilityData/gbfs/blob/v3.0/gbfs.md#vehicle_statusjson">GBFS | ||
* vehicle_status specification</a> for more details. | ||
*/ | ||
public class RentalVehicleFuel { | ||
|
||
/** | ||
* Current fuel percentage, expressed from 0 to 1. | ||
* <p> | ||
* May be {@code null}. | ||
*/ | ||
@Nullable | ||
public final Ratio percent; | ||
|
||
/** | ||
* Distance that the vehicle can travel with the current charge or fuel. | ||
* <p> | ||
* May be {@code null}. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||
*/ | ||
@Nullable | ||
public final Distance range; | ||
|
||
public RentalVehicleFuel(@Nullable Ratio fuelPercent, @Nullable Distance range) { | ||
this.percent = fuelPercent; | ||
this.range = range; | ||
} | ||
|
||
@Nullable | ||
public Double getPercent() { | ||
return this.percent != null ? this.percent.ratio : null; | ||
} | ||
|
||
@Nullable | ||
public Integer getRange() { | ||
return this.range != null ? this.range.toMeters() : null; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
package org.opentripplanner.ext.fares.model; | ||
package org.opentripplanner.transit.model.basic; | ||
|
||
import java.util.Objects; | ||
import org.opentripplanner.utils.tostring.ValueObjectToStringBuilder; | ||
|
||
public class Distance { | ||
|
@@ -8,23 +9,35 @@ 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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This constructor should probably be private. |
||
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) { | ||
public static Distance ofMeters(double value) throws IllegalArgumentException { | ||
if (value < 0) { | ||
throw new IllegalArgumentException("Distance cannot be negative"); | ||
} | ||
|
||
Comment on lines
+22
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to do the validation here as it's done in the constructor. |
||
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"); | ||
} | ||
|
||
Comment on lines
+31
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||
return new Distance(value * METERS_PER_KM); | ||
} | ||
|
||
/** Returns the distance in meters */ | ||
public double toMeters() { | ||
return this.meters; | ||
public int toMeters() { | ||
return (int) Math.round(this.meters); | ||
} | ||
|
||
@Override | ||
|
@@ -36,6 +49,11 @@ public boolean equals(Object other) { | |
} | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(meters, "Distance"); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's enough to just hash the field. |
||
|
||
@Override | ||
public String toString() { | ||
if (meters < METERS_PER_KM) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package org.opentripplanner.transit.model.basic; | ||
|
||
import java.util.Objects; | ||
|
||
public class Ratio { | ||
|
||
public final Double ratio; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This field should be private and it should be exposed through a "asDouble()" or "toDouble()" method (I don't know if we have a naming convention for this, seems like we have mixed usage). |
||
|
||
public Ratio(Double ratio) throws IllegalArgumentException { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We generally don't tell that something throws an IllegalArgumentException. |
||
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"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just hash the field. |
||
} | ||
|
||
@Override | ||
public String toString() { | ||
return this.ratio.toString(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the toString output the number as a percent (like |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,14 +9,21 @@ | |
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; | ||
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; | ||
|
||
public class GbfsFreeVehicleStatusMapper { | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(GbfsFreeVehicleStatusMapper.class); | ||
|
||
private final VehicleRentalSystem system; | ||
|
||
private final Map<String, RentalVehicleType> vehicleTypes; | ||
|
@@ -52,7 +59,40 @@ public VehicleRentalVehicle mapFreeVehicleStatus(GBFSBike vehicle) { | |
vehicle.getLastReported() != null | ||
? Instant.ofEpochSecond((long) (double) vehicle.getLastReported()) | ||
: null; | ||
rentalVehicle.currentRangeMeters = vehicle.getCurrentRangeMeters(); | ||
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) {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to catch npe, when would it happen? |
||
Distance rangeMeters = null; | ||
try { | ||
rangeMeters = | ||
vehicle.getCurrentRangeMeters() != null | ||
? Distance.ofMeters(vehicle.getCurrentRangeMeters()) | ||
: null; | ||
} catch (IllegalArgumentException e) { | ||
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()) != null && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this check, can you double check if it's right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is correct, but this is in an area where a lot of feeds get things wrong so this validation might cause issues but I'm not sure if I'm against this or not. |
||
vehicleTypes.get(vehicle.getVehicleTypeId()).propulsionType != | ||
RentalVehicleType.PropulsionType.HUMAN && | ||
rangeMeters == null | ||
) { | ||
return null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should log a warning here since the whole vehicle is ignored. |
||
} | ||
rentalVehicle.fuel = new RentalVehicleFuel(fuelPercent, rangeMeters); | ||
rentalVehicle.pricingPlanId = vehicle.getPricingPlanId(); | ||
GBFSRentalUris rentalUris = vehicle.getRentalUris(); | ||
if (rentalUris != null) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's enough to mark the field as nullable.