Skip to content
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 support for park and ride itineraries when calculating CO2 emissions #5489

Merged
merged 10 commits into from
Nov 13, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.opentripplanner._support.time.ZoneIds;
Expand All @@ -24,62 +25,47 @@
import org.opentripplanner.transit.model.basic.TransitMode;
import org.opentripplanner.transit.model.framework.Deduplicator;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.opentripplanner.transit.model.network.Route;
import org.opentripplanner.transit.model.organization.Agency;
import org.opentripplanner.transit.model.timetable.Trip;
import org.opentripplanner.transit.model.timetable.TripTimes;

class EmissionsTest {

private DefaultEmissionsService eService;
private EmissionsFilter emissionsFilter;
private static DefaultEmissionsService eService;
private static EmissionsFilter emissionsFilter;

static final ZonedDateTime TIME = OffsetDateTime
.parse("2023-07-20T17:49:06+03:00")
.toZonedDateTime();

private static final Agency subject = Agency
.of(TransitModelForTest.id("F:1"))
.withName("Foo_CO")
.withTimezone("Europe/Helsinki")
private static final StreetLeg STREET_LEG = StreetLeg
.create()
.withMode(TraverseMode.CAR)
.withDistanceMeters(214.4)
.withStartTime(TIME)
.withEndTime(TIME.plus(1, ChronoUnit.HOURS))
sharhio marked this conversation as resolved.
Show resolved Hide resolved
.build();

@BeforeEach
void SetUp() {
private static final Route ROUTE_WITH_EMISSIONS = TransitModelForTest.route(id("1")).build();
private static final Route ROUTE_WITH_ZERO_EMISSIONS = TransitModelForTest.route(id("2")).build();
private static final Route ROUTE_WITHOUT_EMISSIONS_CONFIGURED = TransitModelForTest
.route(id("3"))
.build();

@BeforeAll
static void SetUp() {
Map<FeedScopedId, Double> emissions = new HashMap<>();
emissions.put(new FeedScopedId("F", "1"), (0.12 / 12));
emissions.put(new FeedScopedId("F", "2"), 0.0);
EmissionsDataModel emissionsDataModel = new EmissionsDataModel(emissions, 0.131);
this.eService = new DefaultEmissionsService(emissionsDataModel);
this.emissionsFilter = new EmissionsFilter(eService);
eService = new DefaultEmissionsService(emissionsDataModel);
emissionsFilter = new EmissionsFilter(eService);
}

@Test
void testGetEmissionsForItinerary() {
var stopOne = TransitModelForTest.stopForTest("1:stop1", 60, 25);
var stopTwo = TransitModelForTest.stopForTest("1:stop1", 61, 25);
var stopThree = TransitModelForTest.stopForTest("1:stop1", 62, 25);
var stopPattern = TransitModelForTest.stopPattern(stopOne, stopTwo, stopThree);
var route = TransitModelForTest.route(id("1")).build();
var pattern = TransitModelForTest.tripPattern("1", route).withStopPattern(stopPattern).build();
var stoptime = new StopTime();
var stoptimes = new ArrayList<StopTime>();
stoptimes.add(stoptime);
var trip = Trip
.of(FeedScopedId.parse("FOO:BAR"))
.withMode(TransitMode.BUS)
.withRoute(route)
.build();
var leg = new ScheduledTransitLegBuilder<>()
.withTripTimes(new TripTimes(trip, stoptimes, new Deduplicator()))
.withTripPattern(pattern)
.withBoardStopIndexInPattern(0)
.withAlightStopIndexInPattern(2)
.withStartTime(TIME)
.withEndTime(TIME.plusMinutes(10))
.withServiceDate(TIME.toLocalDate())
.withZoneId(ZoneIds.BERLIN)
.build();
Itinerary i = new Itinerary(List.of(leg));
Itinerary i = new Itinerary(List.of(createTransitLeg(ROUTE_WITH_EMISSIONS)));
assertEquals(
new Grams(2223.902),
emissionsFilter.filter(List.of(i)).get(0).getEmissionsPerPerson().getCo2()
Expand All @@ -88,14 +74,7 @@ void testGetEmissionsForItinerary() {

@Test
void testGetEmissionsForCarRoute() {
var leg = StreetLeg
.create()
.withMode(TraverseMode.CAR)
.withDistanceMeters(214.4)
.withStartTime(TIME)
.withEndTime(TIME.plus(1, ChronoUnit.HOURS))
.build();
Itinerary i = new Itinerary(List.of(leg));
Itinerary i = new Itinerary(List.of(STREET_LEG));
assertEquals(
new Grams(28.0864),
emissionsFilter.filter(List.of(i)).get(0).getEmissionsPerPerson().getCo2()
Expand All @@ -104,58 +83,55 @@ void testGetEmissionsForCarRoute() {

@Test
void testNoEmissionsForFeedWithoutEmissionsConfigured() {
Map<FeedScopedId, Double> emissions = new HashMap<>();
emissions.put(new FeedScopedId("G", "1"), (0.12 / 12));
EmissionsDataModel emissionsDataModel = new EmissionsDataModel(emissions, 0.131);

this.eService = new DefaultEmissionsService(emissionsDataModel);
this.emissionsFilter = new EmissionsFilter(this.eService);

var route = TransitModelForTest.route(id("1")).withAgency(subject).build();
var pattern = TransitModelForTest
.tripPattern("1", route)
.withStopPattern(TransitModelForTest.stopPattern(3))
.build();
var stoptime = new StopTime();
var stoptimes = new ArrayList<StopTime>();
stoptimes.add(stoptime);
var trip = Trip
.of(FeedScopedId.parse("FOO:BAR"))
.withMode(TransitMode.BUS)
.withRoute(route)
.build();
var leg = new ScheduledTransitLegBuilder<>()
.withTripTimes(new TripTimes(trip, stoptimes, new Deduplicator()))
.withTripPattern(pattern)
.withBoardStopIndexInPattern(0)
.withAlightStopIndexInPattern(2)
.withStartTime(TIME)
.withEndTime(TIME.plusMinutes(10))
.withServiceDate(TIME.toLocalDate())
.withZoneId(ZoneIds.BERLIN)
.build();
Itinerary i = new Itinerary(List.of(leg));
Itinerary i = new Itinerary(List.of(createTransitLeg(ROUTE_WITHOUT_EMISSIONS_CONFIGURED)));
assertEquals(null, emissionsFilter.filter(List.of(i)).get(0).getEmissionsPerPerson());
}

@Test
void testZeroEmissionsForItineraryWithZeroEmissions() {
Itinerary i = new Itinerary(List.of(createTransitLeg(ROUTE_WITH_ZERO_EMISSIONS)));
assertEquals(
new Grams(0.0),
emissionsFilter.filter(List.of(i)).get(0).getEmissionsPerPerson().getCo2()
);
}

@Test
void testGetEmissionsForCombinedRoute() {
Itinerary i = new Itinerary(List.of(createTransitLeg(ROUTE_WITH_EMISSIONS), STREET_LEG));
assertEquals(
new Grams(2251.9884),
emissionsFilter.filter(List.of(i)).get(0).getEmissionsPerPerson().getCo2()
);
}

@Test
void testNoEmissionsForCombinedRouteWithoutTransitEmissions() {
Itinerary i = new Itinerary(
List.of(createTransitLeg(ROUTE_WITHOUT_EMISSIONS_CONFIGURED), STREET_LEG)
);
var emissionsResult = emissionsFilter.filter(List.of(i)).get(0).getEmissionsPerPerson() != null
? emissionsFilter.filter(List.of(i)).get(0).getEmissionsPerPerson().getCo2()
: null;
assertEquals(null, emissionsResult);
sharhio marked this conversation as resolved.
Show resolved Hide resolved
}

private ScheduledTransitLeg createTransitLeg(Route route) {
var stoptime = new StopTime();
var stopTimes = new ArrayList<StopTime>();
stopTimes.add(stoptime);
var stopOne = TransitModelForTest.stopForTest("1:stop1", 60, 25);
var stopTwo = TransitModelForTest.stopForTest("1:stop1", 61, 25);
var stopThree = TransitModelForTest.stopForTest("1:stop1", 62, 25);
var stopPattern = TransitModelForTest.stopPattern(stopOne, stopTwo, stopThree);
var route = TransitModelForTest.route(id("2")).build();
var pattern = TransitModelForTest.tripPattern("1", route).withStopPattern(stopPattern).build();
var stoptime = new StopTime();
var stoptimes = new ArrayList<StopTime>();
stoptimes.add(stoptime);
var trip = Trip
.of(FeedScopedId.parse("FOO:BAR"))
.withMode(TransitMode.BUS)
.withRoute(route)
.build();
var leg = new ScheduledTransitLegBuilder<>()
.withTripTimes(new TripTimes(trip, stoptimes, new Deduplicator()))
return new ScheduledTransitLegBuilder<>()
.withTripTimes(new TripTimes(trip, stopTimes, new Deduplicator()))
.withTripPattern(pattern)
.withBoardStopIndexInPattern(0)
.withAlightStopIndexInPattern(2)
Expand All @@ -164,10 +140,5 @@ void testZeroEmissionsForItineraryWithZeroEmissions() {
.withServiceDate(TIME.toLocalDate())
.withZoneId(ZoneIds.BERLIN)
.build();
Itinerary i = new Itinerary(List.of(leg));
assertEquals(
new Grams(0.0),
emissionsFilter.filter(List.of(i)).get(0).getEmissionsPerPerson().getCo2()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,17 @@ public List<Itinerary> filter(List<Itinerary> itineraries) {

calculateCo2EmissionsForCar(carLegs)
.ifPresent(co2 -> {
itinerary.setEmissionsPerPerson(new Emissions(co2));
if (transitLegs.isEmpty()) {
itinerary.setEmissionsPerPerson(new Emissions(co2));
} else if (
itinerary.getEmissionsPerPerson() != null &&
itinerary.getEmissionsPerPerson().getCo2() != null
) {
// Calculate park and ride emissions.
itinerary.setEmissionsPerPerson(
new Emissions(itinerary.getEmissionsPerPerson().getCo2().plus(co2))
);
sharhio marked this conversation as resolved.
Show resolved Hide resolved
}
});
}
return itineraries;
Expand Down