Skip to content

Commit

Permalink
nested CsvResultOptions in requests
Browse files Browse the repository at this point in the history
reverse order of name and ID in output and enum.
string flags are maintained in request but no longer used.
deleted code serves as example of how to use flags.
  • Loading branch information
abyrd committed Feb 16, 2024
1 parent d5f5bec commit e11fc19
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import com.conveyal.r5.analyst.scenario.Scenario;
import com.conveyal.r5.api.util.LegMode;
import com.conveyal.r5.api.util.TransitModes;
import com.conveyal.r5.transit.TransitLayer;
import com.mongodb.QueryBuilder;
import org.apache.commons.codec.digest.DigestUtils;
import org.checkerframework.checker.units.qual.C;

import java.time.LocalDate;
import java.util.ArrayList;
Expand Down Expand Up @@ -182,6 +184,9 @@ public class AnalysisRequest {
*/
public Set<String> flags;

/** Control the details of CSV regional analysis output, including whether to output IDs, names, or both. */
public CsvResultOptions csvResultOptions = new CsvResultOptions();

/**
* Create the R5 `Scenario` from this request.
*/
Expand Down Expand Up @@ -288,6 +293,7 @@ public void populateTask (AnalysisWorkerTask task, UserPermissions userPermissio
task.includeTemporalDensity = includeTemporalDensity;
task.dualAccessibilityThreshold = dualAccessibilityThreshold;
task.flags = flags;
task.csvResultOptions = csvResultOptions;
}

private EnumSet<LegMode> getEnumSetFromString (String s) {
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/com/conveyal/analysis/models/CsvResultOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.conveyal.analysis.models;

import com.conveyal.r5.transit.TransitLayer;
import com.conveyal.r5.transit.TransitLayer.EntityRepresentation;

import static com.conveyal.r5.transit.TransitLayer.EntityRepresentation.ID_ONLY;

/**
* API model type included in analysis requests to control details of CSV regional analysis output.
* This type is shared between AnalysisRequest (Frontend -> Broker) and AnalysisWorkerTask (Broker -> Workers).
* There is precedent for nested compound types shared across those top level request types (see DecayFunction).
*/
public class CsvResultOptions {
public EntityRepresentation routeRepresentation = ID_ONLY;
public EntityRepresentation stopRepresentation = ID_ONLY;
// Only feed ID representation is allowed to be null (no feed IDs at all, the default).
public EntityRepresentation feedRepresentation = null;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.conveyal.r5.analyst.cluster;

import com.conveyal.analysis.models.CsvResultOptions;
import com.conveyal.r5.analyst.FreeFormPointSet;
import com.conveyal.r5.analyst.Grid;
import com.conveyal.r5.analyst.GridTransformWrapper;
Expand Down Expand Up @@ -184,6 +185,9 @@ public abstract class AnalysisWorkerTask extends ProfileRequest {
*/
public Set<String> flags;

/** Control the details of CSV regional analysis output, including whether to output IDs, names, or both. */
public CsvResultOptions csvResultOptions;

/**
* Is this a single point or regional request? Needed to encode types in JSON serialization. Can that type field be
* added automatically with a serializer annotation instead of by defining a getter method and two dummy methods?
Expand Down
20 changes: 4 additions & 16 deletions src/main/java/com/conveyal/r5/analyst/cluster/PathResult.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.conveyal.r5.analyst.cluster;

import com.conveyal.analysis.models.CsvResultOptions;
import com.conveyal.r5.analyst.StreetTimesAndModes;
import com.conveyal.r5.transit.TransitLayer;
import com.conveyal.r5.transit.path.Path;
Expand All @@ -19,9 +20,6 @@
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.conveyal.r5.transit.TransitLayer.EntityRepresentation.ID_ONLY;
import static com.conveyal.r5.transit.TransitLayer.EntityRepresentation.ID_AND_NAME;
import static com.conveyal.r5.transit.TransitLayer.EntityRepresentation.NAME_ONLY;
import static com.google.common.base.Preconditions.checkState;

/**
Expand Down Expand Up @@ -53,7 +51,7 @@ public class PathResult {

private final TransitLayer transitLayer;

private TransitLayer.EntityRepresentation nameOrId;
private final CsvResultOptions csvOptions;

public static final String[] DATA_COLUMNS = new String[]{
"routes",
Expand Down Expand Up @@ -82,17 +80,7 @@ public PathResult(AnalysisWorkerTask task, TransitLayer transitLayer) {
}
iterationsForPathTemplates = new Multimap[nDestinations];
this.transitLayer = transitLayer;
if (task.flags == null) {
nameOrId = ID_ONLY;
} else {
boolean includeEntityNames = task.flags.contains("csv_names");
boolean includeEntityIds = !task.flags.contains("csv_no_ids");
if (includeEntityIds && includeEntityNames) {
this.nameOrId = ID_AND_NAME;
} else if (includeEntityNames) {
this.nameOrId = NAME_ONLY;
}
}
this.csvOptions = task.csvResultOptions;
}

/**
Expand Down Expand Up @@ -125,7 +113,7 @@ public ArrayList<String[]>[] summarizeIterations(Stat stat) {
int nIterations = iterations.size();
checkState(nIterations > 0, "A path was stored without any iterations");
String waits = null, transfer = null, totalTime = null;
String[] path = routeSequence.detailsWithGtfsIds(transitLayer, nameOrId);
String[] path = routeSequence.detailsWithGtfsIds(transitLayer, csvOptions);
double targetValue;
IntStream totalWaits = iterations.stream().mapToInt(i -> i.waitTimes.sum());
if (stat == Stat.MINIMUM) {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/conveyal/r5/transit/TransitLayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ public TIntSet findStopsInGeometry (Geometry geometry) {
}

public enum EntityRepresentation {
ID_ONLY, NAME_ONLY, ID_AND_NAME
ID_ONLY, NAME_ONLY, NAME_AND_ID
}

/**
Expand All @@ -841,7 +841,7 @@ public String routeString (int routeIndex, EntityRepresentation nameOrId) {
}
return switch (nameOrId) {
case NAME_ONLY -> name;
case ID_AND_NAME -> id + " (" + name + ")";
case NAME_AND_ID -> name + " (" + id + ")";
default -> id;
};
}
Expand Down Expand Up @@ -869,7 +869,7 @@ public String stopString(int stopIndex, EntityRepresentation nameOrId) {
}
return switch (nameOrId) {
case NAME_ONLY -> stopName;
case ID_AND_NAME -> stopId + " (" + stopName + ")";
case NAME_AND_ID -> stopName + " (" + stopId + ")";
default -> stopId;
};
}
Expand Down
17 changes: 9 additions & 8 deletions src/main/java/com/conveyal/r5/transit/path/RouteSequence.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.conveyal.r5.transit.path;

import com.conveyal.analysis.models.CsvResultOptions;
import com.conveyal.r5.transit.TransitLayer;
import com.conveyal.r5.transit.TransitLayer.EntityRepresentation;
import gnu.trove.list.TIntList;
Expand All @@ -10,7 +11,7 @@
import java.util.Objects;
import java.util.StringJoiner;

import static com.conveyal.r5.transit.TransitLayer.EntityRepresentation.ID_AND_NAME;
import static com.conveyal.r5.transit.TransitLayer.EntityRepresentation.NAME_AND_ID;

/** A door-to-door path that includes the routes ridden between stops */
public class RouteSequence {
Expand All @@ -31,15 +32,15 @@ public RouteSequence(PatternSequence patternSequence, TransitLayer transitLayer)
}

/** Returns details summarizing this route sequence, using GTFS ids stored in the supplied transitLayer. */
public String[] detailsWithGtfsIds (TransitLayer transitLayer, EntityRepresentation nameOrId){
public String[] detailsWithGtfsIds (TransitLayer transitLayer, CsvResultOptions csvOptions){
StringJoiner routeIds = new StringJoiner("|");
StringJoiner boardStopIds = new StringJoiner("|");
StringJoiner alightStopIds = new StringJoiner("|");
StringJoiner rideTimes = new StringJoiner("|");
for (int i = 0; i < routes.size(); i++) {
routeIds.add(transitLayer.routeString(routes.get(i), nameOrId));
boardStopIds.add(transitLayer.stopString(stopSequence.boardStops.get(i), nameOrId));
alightStopIds.add(transitLayer.stopString(stopSequence.alightStops.get(i), nameOrId));
routeIds.add(transitLayer.routeString(routes.get(i), csvOptions.routeRepresentation));
boardStopIds.add(transitLayer.stopString(stopSequence.boardStops.get(i), csvOptions.stopRepresentation));
alightStopIds.add(transitLayer.stopString(stopSequence.alightStops.get(i), csvOptions.stopRepresentation));
rideTimes.add(String.format("%.1f", stopSequence.rideTimesSeconds.get(i) / 60f));
}
String accessTime = stopSequence.access == null ? null : String.format("%.1f", stopSequence.access.time / 60f);
Expand All @@ -58,9 +59,9 @@ public String[] detailsWithGtfsIds (TransitLayer transitLayer, EntityRepresentat
public Collection<TransitLeg> transitLegs(TransitLayer transitLayer) {
Collection<TransitLeg> transitLegs = new ArrayList<>();
for (int i = 0; i < routes.size(); i++) {
String routeString = transitLayer.routeString(routes.get(i), ID_AND_NAME);
String boardStop = transitLayer.stopString(stopSequence.boardStops.get(i), ID_AND_NAME);
String alightStop = transitLayer.stopString(stopSequence.alightStops.get(i), ID_AND_NAME);
String routeString = transitLayer.routeString(routes.get(i), NAME_AND_ID);
String boardStop = transitLayer.stopString(stopSequence.boardStops.get(i), NAME_AND_ID);
String alightStop = transitLayer.stopString(stopSequence.alightStops.get(i), NAME_AND_ID);
transitLegs.add(new TransitLeg(routeString, stopSequence.rideTimesSeconds.get(i), boardStop, alightStop));
}
return transitLegs;
Expand Down

0 comments on commit e11fc19

Please sign in to comment.