From 7bed9863ab3579cfd5bcf568c586cc9a5bd7f930 Mon Sep 17 00:00:00 2001 From: Kimmo Hujanen Date: Thu, 25 Feb 2021 14:31:38 +0200 Subject: [PATCH 1/5] special route to HSL --- .../org/opentripplanner/common/model/P3.java | 30 +++++++++ .../org/opentripplanner/common/model/T3.java | 59 +++++++++++++++++ .../org/opentripplanner/model/FareRule.java | 2 +- .../routing/core/FareRuleSet.java | 26 ++++++-- .../impl/DefaultFareServiceFactory.java | 12 +++- .../routing/impl/HSLFareServiceImpl.java | 64 ++++++++++++------- 6 files changed, 158 insertions(+), 35 deletions(-) create mode 100644 src/main/java/org/opentripplanner/common/model/P3.java create mode 100644 src/main/java/org/opentripplanner/common/model/T3.java diff --git a/src/main/java/org/opentripplanner/common/model/P3.java b/src/main/java/org/opentripplanner/common/model/P3.java new file mode 100644 index 00000000000..1cb5de7957f --- /dev/null +++ b/src/main/java/org/opentripplanner/common/model/P3.java @@ -0,0 +1,30 @@ +package org.opentripplanner.common.model; + +/** + * An ordered objects of three (the same type) + * + * @param + */ +public class P3 extends T3 { + + private static final long serialVersionUID = 1L; + + public static P3 create(E first, E second, E third) { + return new P3(first, second, third); + } + + public P3(E first, E second, E third) { + super(first, second, third); + } + + public P3(E[] entries) { + super(entries[0], entries[1], entries[2]); + if (entries.length != 3) { + throw new IllegalArgumentException("This only takes arrays of 3 arguments"); + } + } + + public String toString() { + return "P3(" + first + ", " + second + ", " + third + ")"; + } +} diff --git a/src/main/java/org/opentripplanner/common/model/T3.java b/src/main/java/org/opentripplanner/common/model/T3.java new file mode 100644 index 00000000000..ec4877d2c55 --- /dev/null +++ b/src/main/java/org/opentripplanner/common/model/T3.java @@ -0,0 +1,59 @@ +package org.opentripplanner.common.model; + +import java.io.Serializable; + +/** + * An ordered object of three (potentially different types) + */ +public class T3 implements Serializable { + private static final long serialVersionUID = 1L; + + public final E1 first; + + public final E2 second; + + public final E3 third; + + public T3(E1 first, E2 second, E3 third) { + this.first = first; + this.second = second; + this.third = third; + } + + @Override + public int hashCode() { + return (first != null ? first.hashCode() : 0) + (second != null ? second.hashCode() : 0) + (third != null ? third.hashCode() : 0); + } + + @Override + public boolean equals(Object object) { + if (!(object instanceof T3)) return false; + + T3 other = (T3) object; + + if (first == null) { + if (other.first != null) return false; + } else { + if (!first.equals(other.first)) return false; + } + + if (second == null) { + if (other.second != null) return false; + } else { + if (!second.equals(other.second)) return false; + } + + if (third == null) { + if (other.third != null) return false; + } else { + if (!third.equals(other.third)) return false; + } + + return true; + } + + @Override + public String toString() { + return "T3(" + first + ", " + second + ", " + third + ")"; + } +} diff --git a/src/main/java/org/opentripplanner/model/FareRule.java b/src/main/java/org/opentripplanner/model/FareRule.java index 78c166e3c5e..f63ef33c344 100644 --- a/src/main/java/org/opentripplanner/model/FareRule.java +++ b/src/main/java/org/opentripplanner/model/FareRule.java @@ -58,7 +58,7 @@ public void setContainsId(String containsId) { } public String toString() { - return " attribute.getTransferDuration()) { - LOG.debug("transfer time exceeded; {} > {} in fare {}", tripTime, attribute.getTransferDuration(), attribute.getId()); - continue; - } else { - LOG.debug("transfer time OK; {} < {} in fare {}", tripTime, attribute.getTransferDuration(), attribute.getId()); + if(zones.size() > 0) { + // find the best fare that matches this set of rides + for (FareRuleSet ruleSet : fareRules) { + /* another HSL specific change: We do not set rules for every possible zone combination, + but for the largest zone set allowed for a certain ticket type. + This way we need only a few rules instead of hundreds of rules. Good for speed! + */ + if (ruleSet.getContains().containsAll(zones)) { // contains, not equals !! + FareAttribute attribute = ruleSet.getFareAttribute(); + // transfers are evaluated at boarding time + if (attribute.isTransferDurationSet()) { + if(tripTime > attribute.getTransferDuration()) { + LOG.debug("transfer time exceeded; {} > {} in fare {}", tripTime, attribute.getTransferDuration(), attribute.getId()); + continue; + } else { + LOG.debug("transfer time OK; {} < {} in fare {}", tripTime, attribute.getTransferDuration(), attribute.getId()); + } + } + float newFare = getFarePrice(attribute, fareType); + if (newFare < bestFare) { + bestAttribute = attribute; + bestFare = newFare; } - } - float newFare = getFarePrice(attribute, fareType); - if (newFare < bestFare) { - bestAttribute = attribute; - bestFare = newFare; } } + } else if (specialRouteFare != Float.POSITIVE_INFINITY && specialFareAttribute != null) { + bestFare = specialRouteFare; + bestAttribute = specialFareAttribute; } - LOG.debug("HSL {} best for {}", bestAttribute, rides); return new FareAndId(bestFare, bestAttribute == null ? null : bestAttribute.getId()); } } From 12f235550dde0a9bb5292516d23edcf62d15a134 Mon Sep 17 00:00:00 2001 From: Kimmo Hujanen Date: Thu, 25 Feb 2021 14:35:34 +0200 Subject: [PATCH 2/5] revert debug log of fare --- .../org/opentripplanner/routing/impl/HSLFareServiceImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/opentripplanner/routing/impl/HSLFareServiceImpl.java b/src/main/java/org/opentripplanner/routing/impl/HSLFareServiceImpl.java index 2c822bdd5f3..4bfd06ba68b 100644 --- a/src/main/java/org/opentripplanner/routing/impl/HSLFareServiceImpl.java +++ b/src/main/java/org/opentripplanner/routing/impl/HSLFareServiceImpl.java @@ -178,6 +178,7 @@ but visit temporarily (maybe 1 stop only) an 'external' zone */ bestFare = specialRouteFare; bestAttribute = specialFareAttribute; } + LOG.debug("HSL {} best for {}", bestAttribute, rides); return new FareAndId(bestFare, bestAttribute == null ? null : bestAttribute.getId()); } } From a900a57c64a17bbdd40ad54c4d46a652be8918b1 Mon Sep 17 00:00:00 2001 From: Kimmo Hujanen Date: Fri, 26 Feb 2021 08:23:32 +0200 Subject: [PATCH 3/5] no separate route if routeorigindestination -rule --- .../routing/impl/DefaultFareServiceFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/impl/DefaultFareServiceFactory.java b/src/main/java/org/opentripplanner/routing/impl/DefaultFareServiceFactory.java index 193c936a975..9a10176ac73 100644 --- a/src/main/java/org/opentripplanner/routing/impl/DefaultFareServiceFactory.java +++ b/src/main/java/org/opentripplanner/routing/impl/DefaultFareServiceFactory.java @@ -85,9 +85,10 @@ protected void fillFareRules(String agencyId, Collection fareAttr if (route != null) { FeedScopedId routeId = route.getId(); - fareRule.addRoute(routeId); if (origin != null && destination != null) { fareRule.addRouteOriginDestination(routeId.toString(), origin, destination); + } else { + fareRule.addRoute(routeId); } } else { if (origin != null || destination != null) { From f8c82b95ef09a27752a6748c80fc57974d04b442 Mon Sep 17 00:00:00 2001 From: Kimmo Hujanen Date: Fri, 26 Feb 2021 10:58:11 +0200 Subject: [PATCH 4/5] fixing TestFares --- .../org/opentripplanner/model/FareRule.java | 2 +- .../impl/DefaultFareServiceFactory.java | 3 ++ .../routing/algorithm/TestFares.java | 52 ++----------------- 3 files changed, 8 insertions(+), 49 deletions(-) diff --git a/src/main/java/org/opentripplanner/model/FareRule.java b/src/main/java/org/opentripplanner/model/FareRule.java index f63ef33c344..78c166e3c5e 100644 --- a/src/main/java/org/opentripplanner/model/FareRule.java +++ b/src/main/java/org/opentripplanner/model/FareRule.java @@ -58,7 +58,7 @@ public void setContainsId(String containsId) { } public String toString() { - return " Date: Fri, 26 Feb 2021 13:25:56 +0200 Subject: [PATCH 5/5] fix: fuzzy logic --- .../routing/impl/DefaultFareServiceFactory.java | 3 --- .../org/opentripplanner/routing/impl/HSLFareServiceImpl.java | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/org/opentripplanner/routing/impl/DefaultFareServiceFactory.java b/src/main/java/org/opentripplanner/routing/impl/DefaultFareServiceFactory.java index 9a25e1852ff..9a10176ac73 100644 --- a/src/main/java/org/opentripplanner/routing/impl/DefaultFareServiceFactory.java +++ b/src/main/java/org/opentripplanner/routing/impl/DefaultFareServiceFactory.java @@ -89,9 +89,6 @@ protected void fillFareRules(String agencyId, Collection fareAttr fareRule.addRouteOriginDestination(routeId.toString(), origin, destination); } else { fareRule.addRoute(routeId); - if (origin != null || destination != null) { - fareRule.addOriginDestination(origin, destination); - } } } else { if (origin != null || destination != null) { diff --git a/src/main/java/org/opentripplanner/routing/impl/HSLFareServiceImpl.java b/src/main/java/org/opentripplanner/routing/impl/HSLFareServiceImpl.java index 4bfd06ba68b..a8a7a02ee9f 100644 --- a/src/main/java/org/opentripplanner/routing/impl/HSLFareServiceImpl.java +++ b/src/main/java/org/opentripplanner/routing/impl/HSLFareServiceImpl.java @@ -113,7 +113,7 @@ but visit temporarily (maybe 1 stop only) an 'external' zone */ for (FareRuleSet ruleSet : fareRules) { String routeOriginDestination = String.valueOf(ride.route) + ", " + String.valueOf(ride.startZone) + ", " + String.valueOf(ride.endZone); boolean isSpecialRoute = false; - if(ruleSet.getRoutes().size() == 1 && !ruleSet.getRouteOriginDestinations().isEmpty() && ruleSet.getRouteOriginDestinations().toString().indexOf(routeOriginDestination) != -1) { + if(!ruleSet.getRouteOriginDestinations().isEmpty() && ruleSet.getRouteOriginDestinations().toString().indexOf(routeOriginDestination) != -1) { isSpecialRoute = true; } if(isSpecialRoute || (ruleSet.getRoutes().contains(ride.route) &&