Skip to content

Commit

Permalink
put escalator preferences in a sub object in walk preferences
Browse files Browse the repository at this point in the history
  • Loading branch information
tkalvas committed Dec 9, 2024
1 parent 21e183f commit 6f5b5df
Show file tree
Hide file tree
Showing 14 changed files with 228 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public void buildEscalatorEdge(OsmWay escalatorWay, double length) {
issueStore.add(
Issue.issue(
"InvalidDuration",
"Duration for osm node %d is not a valid duration: '%s'; it's replaced with 'Optional.empty()' (unknown).",
escalatorWay.getId(),
"Duration for osm node {} is not a valid duration: '{}'; the value is ignored.",
escalatorWay.url(),
v
)
)
Expand All @@ -59,7 +59,7 @@ public void buildEscalatorEdge(OsmWay escalatorWay, double length) {
Issue.issue(
"InvalidDuration",
"Duration for osm node {} makes implied speed {} be outside acceptable range.",
escalatorWay.getId(),
escalatorWay.url(),
speed
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
import gnu.trove.list.TLongList;
import gnu.trove.list.array.TLongArrayList;
import java.time.Duration;
import java.time.format.DateTimeParseException;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import org.opentripplanner.graph_builder.module.osm.StreetTraversalPermissionPair;
import org.opentripplanner.street.model.StreetTraversalPermission;
import org.opentripplanner.utils.time.DurationUtils;

public class OsmWay extends OsmWithTags {

Expand Down Expand Up @@ -136,7 +134,7 @@ public boolean isEscalator() {
}

public Optional<Duration> getDuration(Consumer<String> errorHandler) {
return getTagAsDuration("duration", errorHandler);
return getTagValueAsDuration("duration", errorHandler);
}

public boolean isForwardEscalator() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,45 +229,51 @@ public OptionalInt getTagAsInt(String tag, Consumer<String> errorHandler) {
* hh:mm
* hh:mm:ss
* and where the leading value is not limited to any maximum.
* See <a href="https://wiki.openstreetmap.org/wiki/Key:duration">OSM wiki definition
* of duration</a>.
*
* @param duration string in format mm, hh:mm, or hh:mm:ss
* @return Duration
* @throws DateTimeParseException on bad input
*/
public static Duration parseOsmDuration(String duration) {
// Unfortunately DateFormatParserBuilder doesn't quite do enough for this case.
// It has the capability for expressing optional parts, so it could express hh(:mm(:ss)?)?
// but it cannot express (hh:)?mm(:ss)? where the existence of (:ss) implies the existence
// of (hh:). Even if it did, it would not be able to handle the cases where hours are
// greater than 23 or (if there is no hours part at all) minutes are greater than 59, which
// are both allowed by the spec and exist in OSM data. Durations are not LocalTimes after
// all, in parsing a LocalTime it makes sense and is correct that hours cannot be more than
// 23 or minutes more than 59, but in durations if you have capped the largest unit, it is
// reasonable for the amount of the largest unit to be as large as it needs to be.
/*
* Unfortunately DateFormatParserBuilder doesn't quite do enough for this case.
* It has the capability for expressing optional parts, so it could express hh(:mm(:ss)?)?
* but it cannot express (hh:)?mm(:ss)? where the existence of (:ss) implies the existence
* of (hh:). Even if it did, it would not be able to handle the cases where hours are
* greater than 23 or (if there is no hours part at all) minutes are greater than 59, which
* are both allowed by the spec and exist in OSM data. Durations are not LocalTimes after
* all, in parsing a LocalTime it makes sense and is correct that hours cannot be more than
* 23 or minutes more than 59, but in durations if you have capped the largest unit, it is
* reasonable for the amount of the largest unit to be as large as it needs to be.
*/
int colonCount = (int) duration.chars().filter(ch -> ch == ':').count();
if (colonCount <= 2) {
try {
int i, j;
long hours, minutes, seconds;
// The first :-separated element can be any width, and has no maximum. It still has
// to be non-negative. The following elements must be 2 characters wide, non-negative,
// and less than 60.
/*
* The first :-separated element can be any width, and has no maximum. It still has
* to be non-negative. The following elements must be 2 characters wide, non-negative,
* and less than 60.
*/
switch (colonCount) {
case 0: // case "m"
case 0: /* case "m" */
minutes = Long.parseLong(duration);
if (minutes >= 0) {
return Duration.ofMinutes(minutes);
}
break;
case 1: // case "h:mm"
case 1: /* case "h:mm" */
i = duration.indexOf(':');
hours = Long.parseLong(duration.substring(0, i));
minutes = Long.parseLong(duration.substring(i + 1));
if (duration.length() - i == 3 && hours >= 0 && minutes >= 0 && minutes < 60) {
return Duration.ofHours(hours).plusMinutes(minutes);
}
break;
default: // case "h:mm:ss"
//case 2:
default: /* case "h:mm:ss" */
i = duration.indexOf(':');
j = duration.indexOf(':', i + 1);
hours = Long.parseLong(duration.substring(0, i));
Expand All @@ -287,14 +293,22 @@ public static Duration parseOsmDuration(String duration) {
break;
}
} catch (NumberFormatException e) {
// fallthrough
/* fallthrough */
}
}
throw new DateTimeParseException("bad clock duration", duration, 0);
throw new DateTimeParseException("Bad OSM duration", duration, 0);
}

public Optional<Duration> getTagAsDuration(String tag, Consumer<String> errorHandler) {
String value = getTag(tag);
/**
* Gets a tag's value, assumes it is an OSM wiki spesified duration, parses and returns it.
* If parsing fails, calls the error handler.
*
* @param key
* @param errorHandler
* @return parsed Duration, or empty
*/
public Optional<Duration> getTagValueAsDuration(String key, Consumer<String> errorHandler) {
String value = getTag(key);
if (value != null) {
try {
return Optional.of(parseOsmDuration(value));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package org.opentripplanner.routing.api.request.preference;

import static org.opentripplanner.utils.lang.DoubleUtils.doubleEquals;

import java.io.Serializable;
import java.util.Objects;
import java.util.function.Consumer;
import org.opentripplanner.utils.tostring.ToStringBuilder;

public class EscalatorPreferences implements Serializable {

public static final EscalatorPreferences DEFAULT = new EscalatorPreferences();

private final double reluctance;
private final double speed;

private EscalatorPreferences() {
this.reluctance = 1.5;
this.speed = 0.45;
}

private EscalatorPreferences(Builder builder) {
reluctance = builder.reluctance;
speed = builder.speed;
}

public static Builder of() {
return new Builder(DEFAULT);
}

public Builder copyOf() {
return new Builder(this);
}

public double reluctance() {
return reluctance;
}

public double speed() {
return speed;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EscalatorPreferences that = (EscalatorPreferences) o;
return (doubleEquals(that.reluctance, reluctance) && doubleEquals(that.speed, speed));
}

@Override
public int hashCode() {
return Objects.hash(speed, reluctance);
}

@Override
public String toString() {
return ToStringBuilder
.of(EscalatorPreferences.class)
.addNum("speed", speed, DEFAULT.speed)
.addNum("reluctance", reluctance, DEFAULT.reluctance)
.toString();
}

public static class Builder {

private final EscalatorPreferences original;
private double reluctance;
private double speed;

public Builder(EscalatorPreferences original) {
this.original = original;
this.reluctance = original.reluctance;
this.speed = original.speed;
}

public EscalatorPreferences original() {
return original;
}

public double speed() {
return speed;
}

public Builder withSpeed(double speed) {
this.speed = speed;
return this;
}

public double reluctance() {
return reluctance;
}

public Builder withReluctance(double reluctance) {
this.reluctance = reluctance;
return this;
}

public Builder apply(Consumer<Builder> body) {
body.accept(this);
return this;
}

public EscalatorPreferences build() {
var newObj = new EscalatorPreferences(this);
return original.equals(newObj) ? original : newObj;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.opentripplanner.routing.api.request.preference;

import static org.opentripplanner.utils.lang.DoubleUtils.doubleEquals;
import static org.opentripplanner.utils.lang.ObjectUtils.ifNotNull;

import java.io.Serializable;
import java.util.Objects;
Expand Down Expand Up @@ -29,8 +30,7 @@ public final class WalkPreferences implements Serializable {
private final double stairsTimeFactor;
private final double safetyFactor;

private final double escalatorReluctance;
private final double escalatorSpeed;
private final EscalatorPreferences escalator;

private WalkPreferences() {
this.speed = 1.33;
Expand All @@ -39,8 +39,7 @@ private WalkPreferences() {
this.stairsReluctance = 2.0;
this.stairsTimeFactor = 3.0;
this.safetyFactor = 1.0;
this.escalatorReluctance = 1.5;
this.escalatorSpeed = 0.45;
this.escalator = EscalatorPreferences.DEFAULT;
}

private WalkPreferences(Builder builder) {
Expand All @@ -50,8 +49,7 @@ private WalkPreferences(Builder builder) {
this.stairsReluctance = Units.reluctance(builder.stairsReluctance);
this.stairsTimeFactor = Units.reluctance(builder.stairsTimeFactor);
this.safetyFactor = Units.reluctance(builder.safetyFactor);
this.escalatorReluctance = Units.reluctance(builder.escalatorReluctance);
this.escalatorSpeed = Units.speed(builder.escalatorSpeed);
this.escalator = builder.escalator;
}

public static Builder of() {
Expand Down Expand Up @@ -111,12 +109,8 @@ public double safetyFactor() {
return safetyFactor;
}

public double escalatorReluctance() {
return escalatorReluctance;
}

public double escalatorSpeed() {
return escalatorSpeed;
public EscalatorPreferences escalator() {
return escalator;
}

@Override
Expand All @@ -131,8 +125,7 @@ public boolean equals(Object o) {
doubleEquals(that.stairsReluctance, stairsReluctance) &&
doubleEquals(that.stairsTimeFactor, stairsTimeFactor) &&
doubleEquals(that.safetyFactor, safetyFactor) &&
doubleEquals(that.escalatorReluctance, escalatorReluctance) &&
doubleEquals(that.escalatorSpeed, escalatorSpeed)
escalator.equals(that.escalator)
);
}

Expand All @@ -145,8 +138,7 @@ public int hashCode() {
stairsReluctance,
stairsTimeFactor,
safetyFactor,
escalatorReluctance,
escalatorSpeed
escalator
);
}

Expand All @@ -160,8 +152,7 @@ public String toString() {
.addNum("stairsReluctance", stairsReluctance, DEFAULT.stairsReluctance)
.addNum("stairsTimeFactor", stairsTimeFactor, DEFAULT.stairsTimeFactor)
.addNum("safetyFactor", safetyFactor, DEFAULT.safetyFactor)
.addNum("escalatorReluctance", escalatorReluctance, DEFAULT.escalatorReluctance)
.addNum("escalatorSpeed", escalatorSpeed, DEFAULT.escalatorSpeed)
.addObj("escalator", escalator, DEFAULT.escalator)
.toString();
}

Expand All @@ -175,8 +166,7 @@ public static class Builder {
private double stairsTimeFactor;
private double safetyFactor;

private double escalatorReluctance;
private double escalatorSpeed;
private EscalatorPreferences escalator;

public Builder(WalkPreferences original) {
this.original = original;
Expand All @@ -186,8 +176,7 @@ public Builder(WalkPreferences original) {
this.stairsReluctance = original.stairsReluctance;
this.stairsTimeFactor = original.stairsTimeFactor;
this.safetyFactor = original.safetyFactor;
this.escalatorReluctance = original.escalatorReluctance;
this.escalatorSpeed = original.escalatorSpeed;
this.escalator = original.escalator;
}

public WalkPreferences original() {
Expand Down Expand Up @@ -254,21 +243,12 @@ public Builder withSafetyFactor(double safetyFactor) {
return this;
}

public double escalatorReluctance() {
return escalatorReluctance;
}

public Builder withEscalatorReluctance(double escalatorReluctance) {
this.escalatorReluctance = escalatorReluctance;
return this;
}

public double escalatorSpeed() {
return escalatorSpeed;
public EscalatorPreferences escalator() {
return escalator;
}

public Builder withEscalatorSpeed(double escalatorSpeed) {
this.escalatorSpeed = escalatorSpeed;
public Builder withEscalator(Consumer<EscalatorPreferences.Builder> body) {
this.escalator = ifNotNull(this.escalator, original.escalator).copyOf().apply(body).build();
return this;
}

Expand Down
Loading

0 comments on commit 6f5b5df

Please sign in to comment.