Skip to content

Commit

Permalink
Fix: Add back walk-reluctance in Transmodel API
Browse files Browse the repository at this point in the history
Chery picked: 5efd85d, b004252, bb31141
  • Loading branch information
t2gran committed Nov 2, 2023
1 parent b16abdc commit b690653
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/ext/graphql/transmodelapi/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ type QueryType {
"Date and time for the earliest time the user is willing to start the journey (if arriveBy=false/not set) or the latest acceptable time of arriving (arriveBy=true). Defaults to now"
dateTime: DateTime,
"Debug the itinerary-filter-chain. OTP will attach a system notice to itineraries instead of removing them. This is very convenient when tuning the filters."
debugItineraryFilter: Boolean = false,
debugItineraryFilter: Boolean = false @deprecated(reason : "Use `itineraryFilter.debug` instead."),
"FOR TESTING ONLY"
extraSearchCoachReluctance: Float,
"A list of filters for which trips should be included. A trip will be included if it matches with at least one filter. An empty list of filters means that all trips should be included. If a search include this parameter, \"whiteListed\", \"banned\" & \"modes.transportModes\" filters will be ignored."
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.opentripplanner.ext.transmodelapi.mapping;

import static org.opentripplanner.ext.transmodelapi.mapping.preferences.BikePreferencesMapper.mapBikePreferences;
import static org.opentripplanner.ext.transmodelapi.mapping.preferences.CarPreferencesMapper.mapCarPreferences;
import static org.opentripplanner.ext.transmodelapi.mapping.preferences.ItineraryFilterPreferencesMapper.mapItineraryFilterPreferences;
import static org.opentripplanner.ext.transmodelapi.mapping.preferences.ItineraryFilterPreferencesMapper.mapRentalPreferences;
import static org.opentripplanner.ext.transmodelapi.mapping.preferences.StreetPreferencesMapper.mapStreetPreferences;
Expand All @@ -19,10 +20,11 @@ static void mapPreferences(
DataFetcherDecorator callWith,
RoutingPreferences.Builder preferences
) {
preferences.withWalk(walk -> mapWalkPreferences(walk, environment, callWith));
preferences.withStreet(street -> mapStreetPreferences(street, environment, preferences.street())
);
preferences.withWalk(walk -> mapWalkPreferences(walk, callWith));
preferences.withBike(bike -> mapBikePreferences(bike, callWith));
preferences.withCar(car -> mapCarPreferences(car, callWith));
preferences.withTransfer(transfer -> mapTransferPreferences(transfer, environment, callWith));
preferences.withTransit(transit -> mapTransitPreferences(transit, environment, callWith));
preferences.withItineraryFilter(itineraryFilter ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,35 @@

public class BikePreferencesMapper {

public static final double WALK_BIKE_RELATIVE_RELUCTANCE = 2.7;

public static void mapBikePreferences(
BikePreferences.Builder bike,
DataFetcherDecorator callWith
) {
callWith.argument("bikeSpeed", bike::withSpeed);
callWith.argument("bikeSwitchTime", bike::withSwitchTime);
callWith.argument("bikeSwitchCost", bike::withSwitchCost);

// These are not wsposed on the Transmodel API
// callWith.argument("bikeSwitchTime", bike::withSwitchTime);
// callWith.argument("bikeSwitchCost", bike::withSwitchCost);

callWith.argument("bicycleOptimisationMethod", bike::withOptimizeType);

// WALK reluctance is used for backwards compatibility, then overridden
callWith.argument(
"walkReluctance",
r -> {
bike.withReluctance((double) r);
bike.withWalkingReluctance(WALK_BIKE_RELATIVE_RELUCTANCE * (double) r);
}
);

// TODO: Override WALK reluctance with BIKE reluctance
// callWith.argument("bike.reluctance", r -> {
// bike.withReluctance((double)r);
// bike.withWalkingReluctance(WALK_BIKE_RELATIVE_RELUCTANCE * (double)r );
//});

if (bike.optimizeType() == BicycleOptimizeType.TRIANGLE) {
bike.withOptimizeTriangle(triangle -> {
callWith.argument("triangleFactors.time", triangle::withTime);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.opentripplanner.ext.transmodelapi.mapping.preferences;

import org.opentripplanner.ext.transmodelapi.support.DataFetcherDecorator;
import org.opentripplanner.routing.api.request.preference.CarPreferences;

public class CarPreferencesMapper {

public static void mapCarPreferences(CarPreferences.Builder car, DataFetcherDecorator callWith) {
// Walk reluctance is used for backward compatibility
callWith.argument("walkReluctance", car::withReluctance);
// UNSUPPORTED PARAMETERS

// Override WALK reluctance with CAR reluctance
// callWith.argument("car.reluctance", car::withReluctance);
// callWith.argument("car.speed", car::withSpeed);
// callWith.argument("car.park.cost", car::withParkCost);
// callWith.argument("car.park.time", car::withParkTime);
// callWith.argument("car.pickup.cost", car::withPickupCost);
// callWith.argument("car.pickup.time", car::withPickupTime);
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package org.opentripplanner.ext.transmodelapi.mapping.preferences;

import graphql.schema.DataFetchingEnvironment;
import org.opentripplanner.ext.transmodelapi.support.DataFetcherDecorator;
import org.opentripplanner.routing.api.request.preference.WalkPreferences;

public class WalkPreferencesMapper {

public static void mapWalkPreferences(
WalkPreferences.Builder walk,
DataFetchingEnvironment environment,
DataFetcherDecorator callWith
) {
callWith.argument("walkBoardCost", walk::withBoardCost);
// This is not part of API
// callWith.argument("walkBoardCost", walk::withBoardCost);
callWith.argument("walkSpeed", walk::withSpeed);
callWith.argument("walkReluctance", walk::withReluctance);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ public static GraphQLFieldDefinition create(
)
.type(Scalars.GraphQLBoolean)
.defaultValue(preferences.itineraryFilter().debug().debugEnabled())
.deprecate("Use `itineraryFilter.debug` instead.")
.build()
)
.argument(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.opentripplanner.ext.transmodelapi._support;

import java.util.Map;
import java.util.function.Consumer;
import org.opentripplanner.ext.transmodelapi.support.DataFetcherDecorator;

public class TestDataFetcherDecorator extends DataFetcherDecorator {

private final Map<String, ?> data;

private TestDataFetcherDecorator(Map<String, ?> data) {
super(null);
this.data = data;
}

public static TestDataFetcherDecorator of(String fieldName, Object value) {
return new TestDataFetcherDecorator(Map.of(fieldName, value));
}

@SuppressWarnings("unchecked")
@Override
public <T> void argument(String name, Consumer<T> consumer) {
T value = (T) data.get(name);
if (value != null) {
consumer.accept(value);
} else {
System.out.println("No mapping for: " + name);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.opentripplanner.ext.transmodelapi.mapping.preferences;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.opentripplanner.ext.transmodelapi.mapping.preferences.BikePreferencesMapper.mapBikePreferences;

import java.util.List;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.opentripplanner.ext.transmodelapi._support.TestDataFetcherDecorator;
import org.opentripplanner.routing.api.request.preference.BikePreferences;
import org.opentripplanner.routing.core.BicycleOptimizeType;

class BikePreferencesMapperTest {

static List<Arguments> mapBikePreferencesTestCases() {
return List.of(
Arguments.of(
"walkReluctance",
10.0,
"BikePreferences{reluctance: 10.0, walkingReluctance: 27.0}"
),
Arguments.of("bikeSpeed", 10.0, "BikePreferences{speed: 10.0}"),
Arguments.of(
"bicycleOptimisationMethod",
BicycleOptimizeType.TRIANGLE,
"BikePreferences{optimizeType: TRIANGLE}"
),
// No effect unless BicycleOptimize is TRIANGLE
Arguments.of("triangleFactors.time", 0.17, "BikePreferences{}"),
Arguments.of("triangleFactors.slope", 0.12, "BikePreferences{}"),
Arguments.of("triangleFactors.safety", 0.13, "BikePreferences{}")
);
}

@ParameterizedTest
@MethodSource("mapBikePreferencesTestCases")
void testMapBikePreferences(String field, Object value, String expected) {
var preferences = BikePreferences.of();
mapBikePreferences(preferences, TestDataFetcherDecorator.of(field, value));
assertEquals(expected, preferences.build().toString());
}

static List<Arguments> mapBikePreferencesOptimizeTriangleTestCases() {
return List.of(
Arguments.of(
"triangleFactors.time",
0.17,
"TimeSlopeSafetyTriangle[time=1.0, slope=0.0, safety=0.0]"
),
Arguments.of(
"triangleFactors.slope",
0.12,
"TimeSlopeSafetyTriangle[time=0.0, slope=1.0, safety=0.0]"
),
Arguments.of(
"triangleFactors.safety",
0.13,
"TimeSlopeSafetyTriangle[time=0.0, slope=0.0, safety=1.0]"
)
);
}

@ParameterizedTest
@MethodSource("mapBikePreferencesOptimizeTriangleTestCases")
void testMapBikePreferencesOptimizeTriangle(String field, Object value, String expected) {
var preferences = BikePreferences.of().withOptimizeType(BicycleOptimizeType.TRIANGLE);
mapBikePreferences(preferences, TestDataFetcherDecorator.of(field, value));
assertEquals(
"BikePreferences{optimizeType: TRIANGLE, optimizeTriangle: " + expected + "}",
preferences.build().toString()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.opentripplanner.ext.transmodelapi.mapping.preferences;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.List;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.opentripplanner.ext.transmodelapi._support.TestDataFetcherDecorator;
import org.opentripplanner.routing.api.request.preference.CarPreferences;

class CarPreferencesMapperTest {

static List<Arguments> mapCarPreferencesTestCases() {
return List.of(Arguments.of("walkReluctance", 7.5, "CarPreferences{reluctance: 7.5}"));
}

@ParameterizedTest
@MethodSource("mapCarPreferencesTestCases")
void mapCarPreferences(String field, Object value, String expected) {
var preferences = CarPreferences.of();
CarPreferencesMapper.mapCarPreferences(preferences, TestDataFetcherDecorator.of(field, value));
assertEquals(expected, preferences.build().toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.opentripplanner.ext.transmodelapi.mapping.preferences;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.List;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.opentripplanner.ext.transmodelapi._support.TestDataFetcherDecorator;
import org.opentripplanner.routing.api.request.preference.WalkPreferences;

class WalkPreferencesMapperTest {

static List<Arguments> mapWalkPreferencesTestCases() {
return List.of(
Arguments.of("walkReluctance", 7.5, "WalkPreferences{reluctance: 7.5}"),
Arguments.of("walkSpeed", 3.2, "WalkPreferences{speed: 3.2}")
);
}

@ParameterizedTest
@MethodSource("mapWalkPreferencesTestCases")
void mapWalkPreferences(String field, Object value, String expected) {
var preferences = WalkPreferences.of();
WalkPreferencesMapper.mapWalkPreferences(
preferences,
TestDataFetcherDecorator.of(field, value)
);
assertEquals(expected, preferences.build().toString());
}
}

0 comments on commit b690653

Please sign in to comment.