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 generalizedCostMaxLimit field to the PageCursor to enable using RemoveTransitIfStreetOnlyIsBetter filter with paging #6474

Open
wants to merge 16 commits into
base: dev-2.x
Choose a base branch
from

Conversation

VillePihlava
Copy link
Contributor

@VillePihlava VillePihlava commented Feb 20, 2025

Summary

This PR adds the generalizedCostMaxLimit field to the PageCursor. This enables using the RemoveTransitIfStreetOnlyIsBetter filter with paging. Before this PR, this was not possible because paging only used the walk mode to create a direct itinerary which made the filter work incorrectly.

Issue

N/A

Unit tests

Changed existing unit tests for compatibility and created new ones. Also performed manual testing.

Documentation

Code comments, no other documentation

@VillePihlava VillePihlava requested a review from a team as a code owner February 20, 2025 12:44
Copy link

codecov bot commented Feb 20, 2025

Codecov Report

Attention: Patch coverage is 93.41317% with 11 lines in your changes missing coverage. Please review.

Project coverage is 70.13%. Comparing base (62b4982) to head (833acec).
Report is 282 commits behind head on dev-2.x.

Files with missing lines Patch % Lines
...del/plan/paging/cursor/DefaultPageCursorInput.java 79.31% 6 Missing ⚠️
...model/plan/paging/cursor/PageCursorSerializer.java 95.83% 1 Missing and 1 partial ⚠️
...rithm/mapping/RouteRequestToFilterChainMapper.java 50.00% 1 Missing and 1 partial ⚠️
...m/filterchain/ItineraryListFilterChainBuilder.java 83.33% 1 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             dev-2.x    #6474      +/-   ##
=============================================
- Coverage      70.31%   70.13%   -0.19%     
- Complexity     18158    18282     +124     
=============================================
  Files           2058     2078      +20     
  Lines          76939    77742     +803     
  Branches        7771     7835      +64     
=============================================
+ Hits           54097    54521     +424     
- Misses         20088    20443     +355     
- Partials        2754     2778      +24     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@VillePihlava
Copy link
Contributor Author

I removed the direct mode search with paging and refactored bestStreetOnlyCost to streetOnlyCost. This should now be ready-for-review.

@VillePihlava VillePihlava changed the title Add bestStreetOnlyCost field to the PageCursor to enable using RemoveTransitIfStreetOnlyIsBetter filter with paging Add streetOnlyCost field to the PageCursor to enable using RemoveTransitIfStreetOnlyIsBetter filter with paging Feb 21, 2025
public class DefaultPageCursorInput implements PageCursorInput {

private final NumItinerariesFilterResults numItinerariesFilterResults;
private final OptionalInt streetOnlyCost;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use optionals for fields, we can although expose it as one through a getter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using another custom Results type here, like NumItinerariesFilterResults, for readability. That would preserve the general idea that the pageCursor depends on results from some filters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a RemoveTransitIfStreetOnlyIsBetterResults record and removed optionals from fields.

Comment on lines 25 to 33
public DefaultPageCursorInput() {
this.numItinerariesFilterResults = null;
this.streetOnlyCost = OptionalInt.empty();
}

public DefaultPageCursorInput(Builder builder) {
this.numItinerariesFilterResults = builder.numItinerariesFilterResults();
this.streetOnlyCost = builder.streetOnlyCost();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these constructors need to be public if we use a builder for constructing this? Is the first constructor necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made these constructors private. The first constructor is used with the of() method

public static class Builder {

private NumItinerariesFilterResults numItinerariesFilterResults;
private OptionalInt streetOnlyCost;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a RemoveTransitIfStreetOnlyIsBetterResults record and removed optionals from fields.

@@ -24,11 +25,17 @@ public record PageCursor(
Instant earliestDepartureTime,
Instant latestArrivalTime,
Duration searchWindow,
@Nullable ItinerarySortKey itineraryPageCut
@Nullable ItinerarySortKey itineraryPageCut,
OptionalInt streetOnlyCost
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a RemoveTransitIfStreetOnlyIsBetterResults record and removed optionals from fields. Here I use the field generalizedCostMaxLimit that can be null

@@ -50,18 +51,23 @@ public PageCursorFactory withOriginalSearch(
}

/**
* This adds the page cursor input to the factory. The cursor input can contain information about filtering results
* or the best street only cost.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* or the best street only cost.
* or the street only cost.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the comment and removed the mention of the street only cost

Comment on lines 24 to 28
public RemoveTransitIfStreetOnlyIsBetter(
CostLinearFunction costLimitFunction,
OptionalInt streetOnlyCost,
Consumer<OptionalInt> streetOnlyCostSubscriber
) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document when the streetOnlyCost is present and when the subscriber is present.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created documentation for this method

return List.of();
} else if (minStreetCost.isPresent() && streetOnlyCost.isPresent()) {
// If both the minStreetCost and streetOnlyCost are present, take the minimum value.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this possible a case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be a possible case since the walk direct search is removed with paging. I changed this to throw an error if this case happens

@@ -46,6 +48,11 @@ public static ItineraryListFilterChain createFilterChain(
builder = builder.withPagingDeduplicationFilter(request.pageCursor().itineraryPageCut());
}

// The page cursor has best street only cost information only in certain cases.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could document what those certain cases are.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I documented this

Comment on lines -96 to -102
// If no direct mode is set, then we set one.
// See {@link FilterTransitWhenDirectModeIsEmpty}
var emptyDirectModeHandler = new FilterTransitWhenDirectModeIsEmpty(
request.journey().direct().mode()
);

request.journey().direct().setMode(emptyDirectModeHandler.resolveDirectMode());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this only used when paging or also when user decided to search with transitOnly: true? I don't know if we should change that behaviour.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with transitOnly: true the mode gets unset here

so to me it seems that this is not related to transitOnly

@@ -17,6 +18,8 @@

public class RemoveTransitIfStreetOnlyIsBetterTest implements PlanTestConstants {

OptionalInt subscribeResult = OptionalInt.empty();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional as a field here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a RemoveTransitIfStreetOnlyIsBetterResults record and removed optionals from fields

Comment on lines 144 to 145
it -> pageCursorInputBuilder = pageCursorInputBuilder.withNumItinerariesFilterResults(it),
it -> pageCursorInputBuilder = pageCursorInputBuilder.withStreetOnlyCost(it)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit strange to pass the builder functions directly into the filter builder. Consider making filter results vars for each of the two filters here, and then passing the filter results into the pageCursorInputBuilder later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created separate variables for the subscriber results. I build the DefaultPageCursorInput later in the createPagingService method

@VillePihlava VillePihlava changed the title Add streetOnlyCost field to the PageCursor to enable using RemoveTransitIfStreetOnlyIsBetter filter with paging Add generalizedCostMaxLimit field to the PageCursor to enable using RemoveTransitIfStreetOnlyIsBetter filter with paging Mar 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants