Various routing fixes/refactoring

This commit is contained in:
dkeen@dkeen-laptop 2012-04-29 09:42:54 -07:00
parent a12884cdcb
commit e7ec1f5978
11 changed files with 267 additions and 141 deletions

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dougkeen.bart" package="com.dougkeen.bart"
android:versionCode="16" android:versionCode="17"
android:versionName="1.2.3" > android:versionName="1.2.4" >
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
@ -10,7 +10,7 @@
<uses-sdk android:minSdkVersion="7" /> <uses-sdk android:minSdkVersion="7" />
<application <application
android:debuggable="false" android:debuggable="true"
android:icon="@drawable/icon" android:icon="@drawable/icon"
android:label="@string/app_name" > android:label="@string/app_name" >
<activity <activity

View File

@ -21,7 +21,6 @@ public class AddRouteActivity extends Activity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.add_favorite); setContentView(R.layout.add_favorite);

View File

@ -243,6 +243,12 @@ public class ViewDeparturesActivity extends ListActivity {
} }
protected void processLatestDepartures(RealTimeDepartures result) { protected void processLatestDepartures(RealTimeDepartures result) {
if (result.getDepartures().isEmpty()) {
result.includeTransferRoutes();
}
if (result.getDepartures().isEmpty()) {
result.includeDoubleTransferRoutes();
}
if (result.getDepartures().isEmpty()) { if (result.getDepartures().isEmpty()) {
final TextView textView = (TextView) findViewById(android.R.id.empty); final TextView textView = (TextView) findViewById(android.R.id.empty);
textView.setText(R.string.no_data_message); textView.setText(R.string.no_data_message);
@ -356,6 +362,8 @@ public class ViewDeparturesActivity extends ListActivity {
int lastSearchIndex = 0; int lastSearchIndex = 0;
int tripCount = mLatestScheduleInfo.getTrips().size(); int tripCount = mLatestScheduleInfo.getTrips().size();
boolean departureUpdated = false; boolean departureUpdated = false;
Departure lastUnestimatedTransfer = null;
int departuresWithoutEstimates = 0;
for (int departureIndex = 0; departureIndex < departuresCount; departureIndex++) { for (int departureIndex = 0; departureIndex < departuresCount; departureIndex++) {
Departure departure = mDeparturesAdapter.getItem(departureIndex); Departure departure = mDeparturesAdapter.getItem(departureIndex);
for (int i = lastSearchIndex; i < tripCount; i++) { for (int i = lastSearchIndex; i < tripCount; i++) {
@ -369,9 +377,10 @@ public class ViewDeparturesActivity extends ListActivity {
- departure.getMeanEstimate()); - departure.getMeanEstimate());
final long millisUntilTripDeparture = trip.getDepartureTime() final long millisUntilTripDeparture = trip.getDepartureTime()
- System.currentTimeMillis(); - System.currentTimeMillis();
final int equalityTolerance = (departure.getOrigin() != null) ? departure final int equalityTolerance = (departure.getOrigin() != null) ? Math
.getOrigin().departureEqualityTolerance .max(departure.getOrigin().departureEqualityTolerance,
: Station.DEFAULT_DEPARTURE_EQUALITY_TOLERANCE; ScheduleItem.SCHEDULE_ITEM_DEPARTURE_EQUALS_TOLERANCE)
: ScheduleItem.SCHEDULE_ITEM_DEPARTURE_EQUALS_TOLERANCE;
if (departure.getOrigin() != null if (departure.getOrigin() != null
&& departure.getOrigin().longStationLinger && departure.getOrigin().longStationLinger
&& departure.hasDeparted() && departure.hasDeparted()
@ -380,6 +389,11 @@ public class ViewDeparturesActivity extends ListActivity {
departure.setArrivalTimeOverride(trip.getArrivalTime()); departure.setArrivalTimeOverride(trip.getArrivalTime());
lastSearchIndex = i; lastSearchIndex = i;
departureUpdated = true; departureUpdated = true;
if (lastUnestimatedTransfer != null) {
lastUnestimatedTransfer.setArrivalTimeOverride(trip
.getArrivalTime());
departuresWithoutEstimates--;
}
break; break;
} else if (departTimeDiff <= (equalityTolerance + departure } else if (departTimeDiff <= (equalityTolerance + departure
.getUncertaintySeconds() * 1000) .getUncertaintySeconds() * 1000)
@ -388,13 +402,27 @@ public class ViewDeparturesActivity extends ListActivity {
departure.setEstimatedTripTime(trip.getTripLength()); departure.setEstimatedTripTime(trip.getTripLength());
lastSearchIndex = i; lastSearchIndex = i;
departureUpdated = true; departureUpdated = true;
if (lastUnestimatedTransfer != null) {
lastUnestimatedTransfer.setArrivalTimeOverride(trip
.getArrivalTime());
departuresWithoutEstimates--;
}
break; break;
} }
} }
if (!departure.hasEstimatedTripTime() && localAverageLength > 0) { // Don't estimate for non-scheduled transfers
departure.setEstimatedTripTime(localAverageLength); if (!departure.getRequiresTransfer()) {
} else if (!departure.hasEstimatedTripTime()) { if (!departure.hasEstimatedTripTime() && localAverageLength > 0) {
departure.setEstimatedTripTime(mAverageTripLength); departure.setEstimatedTripTime(localAverageLength);
} else if (!departure.hasEstimatedTripTime()) {
departure.setEstimatedTripTime(mAverageTripLength);
}
} else if (departure.getRequiresTransfer()
&& !departure.hasAnyArrivalEstimate()) {
lastUnestimatedTransfer = departure;
}
if (!departure.hasAnyArrivalEstimate()) {
departuresWithoutEstimates++;
} }
} }
@ -418,6 +446,10 @@ public class ViewDeparturesActivity extends ListActivity {
getContentResolver().update(mUri, contentValues, null, null); getContentResolver().update(mUri, contentValues, null, null);
} }
if (departuresWithoutEstimates > 0) {
scheduleScheduleInfoFetch(20000);
}
} }
private void scheduleDepartureFetch(int millisUntilExecute) { private void scheduleDepartureFetch(int millisUntilExecute) {

View File

@ -1,5 +1,6 @@
package com.dougkeen.bart.model; package com.dougkeen.bart.model;
import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import android.content.Context; import android.content.Context;
@ -179,6 +180,10 @@ public class Departure implements Parcelable, Comparable<Departure> {
return this.estimatedTripTime > 0; return this.estimatedTripTime > 0;
} }
public boolean hasAnyArrivalEstimate() {
return this.estimatedTripTime > 0 || this.arrivalTimeOverride > 0;
}
public int getUncertaintySeconds() { public int getUncertaintySeconds() {
return (int) (maxEstimate - minEstimate + 1000) / 2000; return (int) (maxEstimate - minEstimate + 1000) / 2000;
} }
@ -367,6 +372,7 @@ public class Departure implements Parcelable, Comparable<Departure> {
@Override @Override
public String toString() { public String toString() {
java.text.DateFormat format = SimpleDateFormat.getTimeInstance();
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append(destination); builder.append(destination);
if (requiresTransfer) { if (requiresTransfer) {
@ -374,6 +380,8 @@ public class Departure implements Parcelable, Comparable<Departure> {
} }
builder.append(", "); builder.append(", ");
builder.append(getCountdownText()); builder.append(getCountdownText());
builder.append(", ");
builder.append(format.format(new Date(getMeanEstimate())));
return builder.toString(); return builder.toString();
} }

View File

@ -41,30 +41,7 @@ public enum Line {
Station.DALY, Station.BALB, Station.GLEN, Station._24TH, Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
Station._16TH, Station.CIVC, Station.POWL, Station.MONT, Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
Station.EMBR, Station.WOAK, Station.ASHB, Station.DBRK, Station.EMBR, Station.WOAK, Station.ASHB, Station.DBRK,
Station.NBRK, Station.PLZA, Station.DELN, Station.RICH), Station.NBRK, Station.PLZA, Station.DELN, Station.RICH);
YELLOW_GREEN_SCHEDULED_TRANSFER(true, YELLOW, GREEN, Station.MLBR,
Station.SFIA, Station.SBRN, Station.SSAN, Station.COLM,
Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
Station.EMBR, Station.WOAK, Station.LAKE, Station.FTVL,
Station.COLS, Station.SANL, Station.BAYF, Station.HAYW,
Station.SHAY, Station.UCTY, Station.FRMT),
YELLOW_BLUE_SCHEDULED_TRANSFER(true, YELLOW, BLUE, Station.MLBR,
Station.SFIA, Station.SBRN, Station.SSAN, Station.COLM,
Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
Station.EMBR, Station.WOAK, Station.LAKE, Station.FTVL,
Station.COLS, Station.SANL, Station.BAYF, Station.CAST,
Station.WDUB, Station.DUBL),
YELLOW_RED_SCHEDULED_TRANSFER(YELLOW, RED, Station.MLBR, Station.SFIA,
Station.SBRN, Station.SSAN, Station.COLM, Station.DALY,
Station.BALB, Station.GLEN, Station._24TH, Station._16TH,
Station.CIVC, Station.POWL, Station.MONT, Station.EMBR,
Station.WOAK, Station.ASHB, Station.DBRK, Station.NBRK,
Station.PLZA, Station.DELN, Station.RICH),
ORANGE_BLUE_SCHEDULED_TRANSFER(true, ORANGE, BLUE, Station.FRMT,
Station.UCTY, Station.SHAY, Station.HAYW, Station.BAYF,
Station.CAST, Station.WDUB, Station.DUBL);
public final List<Station> stations; public final List<Station> stations;
@ -112,6 +89,16 @@ public enum Line {
return lines; return lines;
} }
public static Collection<Line> getLinesWithStations(Station station1, Station station2) {
Collection<Line> lines = new ArrayList<Line>();
for (Line line : Line.values()) {
if (line.stations.contains(station1) && line.stations.contains(station2)) {
lines.add(line);
}
}
return lines;
}
public static Set<Station> getPotentialDestinations(Station station) { public static Set<Station> getPotentialDestinations(Station station) {
Set<Station> destinations = new TreeSet<Station>(); Set<Station> destinations = new TreeSet<Station>();

View File

@ -4,13 +4,13 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
public class RealTimeDepartures { public class RealTimeDepartures {
public RealTimeDepartures(Station origin, Station destination, public RealTimeDepartures(Station origin, Station destination,
List<Route> routes) { List<Route> routes) {
this.origin = origin; this.origin = origin;
this.destination = destination; this.destination = destination;
this.routes = routes; this.routes = routes;
this.unfilteredDepartures = new ArrayList<Departure>();
} }
private Station origin; private Station origin;
@ -19,6 +19,8 @@ public class RealTimeDepartures {
private List<Departure> departures; private List<Departure> departures;
final private List<Departure> unfilteredDepartures;
private List<Route> routes; private List<Route> routes;
public Station getOrigin() { public Station getOrigin() {
@ -56,7 +58,29 @@ public class RealTimeDepartures {
this.departures = departures; this.departures = departures;
} }
public void includeTransferRoutes() {
routes.addAll(origin.getTransferRoutes(destination));
rebuildFilteredDepaturesCollection();
}
public void includeDoubleTransferRoutes() {
routes.addAll(origin.getDoubleTransferRoutes(destination));
rebuildFilteredDepaturesCollection();
}
private void rebuildFilteredDepaturesCollection() {
getDepartures().clear();
for (Departure departure : unfilteredDepartures) {
addDepartureIfApplicable(departure);
}
}
public void addDeparture(Departure departure) { public void addDeparture(Departure departure) {
unfilteredDepartures.add(departure);
addDepartureIfApplicable(departure);
}
private void addDepartureIfApplicable(Departure departure) {
Station destination = Station.getByAbbreviation(departure Station destination = Station.getByAbbreviation(departure
.getDestinationAbbreviation()); .getDestinationAbbreviation());
if (departure.getLine() == null) if (departure.getLine() == null)

View File

@ -1,9 +1,12 @@
package com.dougkeen.bart.model; package com.dougkeen.bart.model;
import java.util.Collection;
public class Route { public class Route {
private Station origin; private Station origin;
private Station destination; private Station destination;
private Line line; private Line directLine;
private Collection<Line> transferLines;
private boolean requiresTransfer; private boolean requiresTransfer;
private Station transferStation; private Station transferStation;
private String direction; private String direction;
@ -26,12 +29,20 @@ public class Route {
this.destination = destination; this.destination = destination;
} }
public Line getLine() { public Line getDirectLine() {
return line; return directLine;
} }
public void setLine(Line line) { public void setDirectLine(Line line) {
this.line = line; this.directLine = line;
}
public Collection<Line> getTransferLines() {
return transferLines;
}
public void setTransferLines(Collection<Line> transferLines) {
this.transferLines = transferLines;
} }
public boolean hasTransfer() { public boolean hasTransfer() {
@ -82,7 +93,7 @@ public class Route {
builder.append(", destination="); builder.append(", destination=");
builder.append(destination); builder.append(destination);
builder.append(", line="); builder.append(", line=");
builder.append(line); builder.append(directLine);
builder.append(", requiresTransfer="); builder.append(", requiresTransfer=");
builder.append(requiresTransfer); builder.append(requiresTransfer);
builder.append(", transferStation="); builder.append(", transferStation=");
@ -99,13 +110,15 @@ public class Route {
public boolean trainDestinationIsApplicable(Station lineDestination, public boolean trainDestinationIsApplicable(Station lineDestination,
Line viaLine) { Line viaLine) {
Line routeLine = getLine(); Line routeLine = getDirectLine();
if (routeLine.transferLine1 != null if (routeLine.transferLine1 != null
&& viaLine.equals(routeLine.transferLine1)) { && viaLine.equals(routeLine.transferLine1)) {
return true; return true;
} else if (routeLine.transferLine2 != null } else if (routeLine.transferLine2 != null
&& viaLine.equals(routeLine.transferLine2)) { && viaLine.equals(routeLine.transferLine2)) {
return true; return true;
} else if (requiresTransfer && transferLines != null && !transferLines.isEmpty()) {
return transferLines.contains(viaLine);
} else { } else {
int originIndex = viaLine.stations.indexOf(origin); int originIndex = viaLine.stations.indexOf(origin);
int routeDestinationIndex = viaLine.stations.indexOf(destination); int routeDestinationIndex = viaLine.stations.indexOf(destination);

View File

@ -1,5 +1,9 @@
package com.dougkeen.bart.model; package com.dougkeen.bart.model;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ScheduleItem { public class ScheduleItem {
public ScheduleItem() { public ScheduleItem() {
@ -12,6 +16,8 @@ public class ScheduleItem {
this.destination = destination; this.destination = destination;
} }
public static final int SCHEDULE_ITEM_DEPARTURE_EQUALS_TOLERANCE = 120000;
private Station origin; private Station origin;
private Station destination; private Station destination;
private String fare; private String fare;
@ -83,4 +89,27 @@ public class ScheduleItem {
public void setTrainHeadStation(String trainHeadStation) { public void setTrainHeadStation(String trainHeadStation) {
this.trainHeadStation = trainHeadStation; this.trainHeadStation = trainHeadStation;
} }
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
DateFormat format = SimpleDateFormat.getTimeInstance();
builder.append("ScheduleItem [origin=");
builder.append(origin);
builder.append(", destination=");
builder.append(destination);
builder.append(", fare=");
builder.append(fare);
builder.append(", departureTime=");
builder.append(format.format(new Date(departureTime)));
builder.append(", arrivalTime=");
builder.append(format.format(new Date(arrivalTime)));
builder.append(", bikesAllowed=");
builder.append(bikesAllowed);
builder.append(", trainHeadStation=");
builder.append(trainHeadStation);
builder.append("]");
return builder.toString();
}
} }

View File

@ -1,59 +1,58 @@
package com.dougkeen.bart.model; package com.dougkeen.bart.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import android.util.Log; import android.util.Log;
public enum Station { public enum Station {
_12TH("12th", "12th St./Oakland City Center", true, false, false, "bayf"), _12TH("12th", "12th St./Oakland City Center", false, false, "bayf", "bayf"),
_16TH("16th", "16th St. Mission", false, false, false), _16TH("16th", "16th St. Mission", false, false),
_19TH("19th", "19th St./Oakland", true, false, false, "bayf"), _19TH("19th", "19th St./Oakland", false, false, "bayf", "bayf"),
_24TH("24th", "24th St. Mission", false, false, false), _24TH("24th", "24th St. Mission", false, false),
ASHB("ashb", "Ashby", true, false, false, "mcar"), ASHB("ashb", "Ashby", false, false, "mcar", "mcar"),
BALB("balb", "Balboa Park", false, false, false), BALB("balb", "Balboa Park", false, false),
BAYF("bayf", "Bay Fair", true, true, false, "mcar"), BAYF("bayf", "Bay Fair", true, false, "mcar", "mcar"),
CAST("cast", "Castro Valley", true, false, false, "bayf"), CAST("cast", "Castro Valley", false, false, "bayf", "bayf"),
CIVC("civc", "Civic Center", false, false, false), CIVC("civc", "Civic Center", false, false),
COLS("cols", "Coliseum/Oakland Airport", true, true, false, "mcar"), COLS("cols", "Coliseum/Oakland Airport", true, false, "mcar", "mcar"),
COLM("colm", "Colma", true, false, false, "balb", "balb"), COLM("colm", "Colma", false, false, "balb", "balb"),
CONC("conc", "Concord", true, false, false, "mcar"), CONC("conc", "Concord", false, false, "mcar", "mcar"),
DALY("daly", "Daly City", false, false, false), DALY("daly", "Daly City", false, false),
DBRK("dbrk", "Downtown Berkeley", true, false, false, "mcar"), DBRK("dbrk", "Downtown Berkeley", false, false, "mcar", "mcar"),
DUBL("dubl", "Dublin/Pleasanton", true, false, true, "bayf", "bayf", true, DUBL("dubl", "Dublin/Pleasanton", false, true, "bayf", "bayf", true, 719999),
DELN("deln", "El Cerrito del Norte", false, false, "mcar", "mcar"),
PLZA("plza", "El Cerrito Plaza", false, false, "mcar", "mcar"),
EMBR("embr", "Embarcadero", false, false),
FRMT("frmt", "Fremont", true, true, "bayf", "bayf", true, 299999),
FTVL("ftvl", "Fruitvale", true, false, "mcar", "mcar"),
GLEN("glen", "Glen Park", false, false),
HAYW("hayw", "Hayward", true, false, "bayf", "bayf"),
LAFY("lafy", "Lafayette", false, false, "mcar", "mcar"),
LAKE("lake", "Lake Merritt", true, false, "mcar", "mcar"),
MCAR("mcar", "MacArthur", false, false, "bayf", "bayf"),
MLBR("mlbr", "Millbrae", false, true, "balb", "balb", true, 719999),
MONT("mont", "Montgomery St.", false, false),
NBRK("nbrk", "North Berkeley", false, false, "mcar", "mcar"),
NCON("ncon", "North Concord/Martinez", false, false, "mcar", "mcar"),
ORIN("orin", "Orinda", false, false, "mcar", "mcar"),
PITT("pitt", "Pittsburg/Bay Point", false, true, "mcar", "mcar", true,
719999), 719999),
DELN("deln", "El Cerrito del Norte", true, false, false, "mcar"), PHIL("phil", "Pleasant Hill", false, false, "mcar", "mcar"),
PLZA("plza", "El Cerrito Plaza", true, false, false, "mcar"), POWL("powl", "Powell St.", false, false),
EMBR("embr", "Embarcadero", false, false, false), RICH("rich", "Richmond", false, true, "mcar", "mcar", true, 299999),
FRMT("frmt", "Fremont", true, true, true, "bayf", "bayf", true, 299999), ROCK("rock", "Rockridge", false, false, "mcar", "mcar"),
FTVL("ftvl", "Fruitvale", true, true, false, "mcar"), SBRN("sbrn", "San Bruno", false, false, "balb", "balb"),
GLEN("glen", "Glen Park", false, false, false), SANL("sanl", "San Leandro", true, false, "mcar", "mcar"),
HAYW("hayw", "Hayward", true, true, false, "bayf"), SFIA("sfia", "SFO Airport", false, false, "balb", "balb", true, 719999),
LAFY("lafy", "Lafayette", true, false, false, "mcar"), SHAY("shay", "South Hayward", true, false, "bayf", "bayf"),
LAKE("lake", "Lake Merritt", true, true, false, "mcar"), SSAN("ssan", "South San Francisco", false, false, "balb", "balb"),
MCAR("mcar", "MacArthur", true, false, false, "bayf"), UCTY("ucty", "Union City", true, false, "bayf", "bayf"),
MLBR("mlbr", "Millbrae", true, false, true, "balb", "balb", true, 719999), WCRK("wcrk", "Walnut Creek", false, false, "mcar", "mcar"),
MONT("mont", "Montgomery St.", false, false, false), WDUB("wdub", "West Dublin/Pleasanton", false, false, "bayf", "bayf"),
NBRK("nbrk", "North Berkeley", true, false, false, "mcar"), WOAK("woak", "West Oakland", false, false),
NCON("ncon", "North Concord/Martinez", true, false, false, "mcar"), SPCL("spcl", "Special", false, false);
ORIN("orin", "Orinda", true, false, false, "mcar"),
PITT("pitt", "Pittsburg/Bay Point", true, false, true, "mcar", "mcar",
true, 719999),
PHIL("phil", "Pleasant Hill", true, false, false, "mcar"),
POWL("powl", "Powell St.", false, false, false),
RICH("rich", "Richmond", true, false, true, "mcar", "mcar", true, 299999),
ROCK("rock", "Rockridge", true, false, false, "mcar"),
SBRN("sbrn", "San Bruno", true, false, false, "balb", "balb"),
SANL("sanl", "San Leandro", true, true, false, "mcar"),
SFIA("sfia", "SFO Airport", true, false, false, "sbrn", "balb", true,
719999),
SHAY("shay", "South Hayward", true, true, false, "bayf"),
SSAN("ssan", "South San Francisco", true, false, false, "balb", "balb"),
UCTY("ucty", "Union City", true, true, false, "bayf"),
WCRK("wcrk", "Walnut Creek", true, false, false, "mcar"),
WDUB("wdub", "West Dublin/Pleasanton", true, false, false, "bayf"),
WOAK("woak", "West Oakland", false, false, false),
SPCL("spcl", "Special", false, false, false);
public final String abbreviation; public final String abbreviation;
public final String name; public final String name;
@ -67,36 +66,35 @@ public enum Station {
public final static int DEFAULT_DEPARTURE_EQUALITY_TOLERANCE = 59999; public final static int DEFAULT_DEPARTURE_EQUALITY_TOLERANCE = 59999;
private Station(String abbreviation, String name, boolean transferFriendly, private Station(String abbreviation, String name, boolean invertDirection,
boolean invertDirection, boolean endOfLine) { boolean endOfLine) {
this(abbreviation, name, transferFriendly, invertDirection, endOfLine, this(abbreviation, name, invertDirection, endOfLine, null, null, false,
null, null, false, DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
}
private Station(String abbreviation, String name, boolean transferFriendly,
boolean invertDirection, boolean endOfLine, String transferStation) {
this(abbreviation, name, transferFriendly, invertDirection, endOfLine,
transferStation, null, false,
DEFAULT_DEPARTURE_EQUALITY_TOLERANCE); DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
} }
private Station(String abbreviation, String name, boolean transferFriendly, private Station(String abbreviation, String name, boolean invertDirection,
boolean invertDirection, boolean endOfLine, boolean endOfLine, String transferStation) {
String inboundTransferStation, String outboundTransferStation) { this(abbreviation, name, invertDirection, endOfLine, transferStation,
this(abbreviation, name, transferFriendly, invertDirection, endOfLine, null, false, DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
}
private Station(String abbreviation, String name, boolean invertDirection,
boolean endOfLine, String inboundTransferStation,
String outboundTransferStation) {
this(abbreviation, name, invertDirection, endOfLine,
inboundTransferStation, outboundTransferStation, false, inboundTransferStation, outboundTransferStation, false,
DEFAULT_DEPARTURE_EQUALITY_TOLERANCE); DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
} }
private Station(String abbreviation, String name, boolean transferFriendly, private Station(String abbreviation, String name, boolean invertDirection,
boolean invertDirection, boolean endOfLine, boolean endOfLine, String inboundTransferStation,
String inboundTransferStation, String outboundTransferStation, String outboundTransferStation, boolean longStationLinger,
boolean longStationLinger, int departureEqualityTolerance) { int departureEqualityTolerance) {
this.abbreviation = abbreviation; this.abbreviation = abbreviation;
this.name = name; this.name = name;
this.invertDirection = invertDirection; this.invertDirection = invertDirection;
this.inboundTransferStation = inboundTransferStation; this.inboundTransferStation = inboundTransferStation;
this.transferFriendly = transferFriendly; this.transferFriendly = outboundTransferStation != null;
this.outboundTransferStation = outboundTransferStation; this.outboundTransferStation = outboundTransferStation;
this.endOfLine = endOfLine; this.endOfLine = endOfLine;
this.longStationLinger = longStationLinger; this.longStationLinger = longStationLinger;
@ -141,64 +139,95 @@ public enum Station {
return false; return false;
} }
public List<Route> getRoutesForDestination(Station dest) { public List<Route> getDirectRoutesForDestination(Station dest) {
return getRoutesForDestination(dest, null); return getDirectRoutesForDestination(this, dest, null, null);
} }
public List<Route> getRoutesForDestination(Station dest, public List<Route> getDirectRoutesForDestination(Station origin,
Station transferStation) { Station dest, Station transferStation,
Collection<Line> transferLines) {
if (dest == null) if (dest == null)
return null; return null;
Boolean isNorth = null; Boolean isNorth = null;
List<Route> returnList = new ArrayList<Route>(); List<Route> returnList = new ArrayList<Route>();
for (Line line : Line.values()) { final Collection<Line> applicableLines = Line.getLinesWithStations(
this, dest);
for (Line line : applicableLines) {
int origIndex = line.stations.indexOf(this); int origIndex = line.stations.indexOf(this);
if (origIndex < 0)
continue;
int destIndex = line.stations.indexOf(dest); int destIndex = line.stations.indexOf(dest);
if (destIndex < 0)
continue;
isNorth = (origIndex < destIndex); isNorth = (origIndex < destIndex);
if (line.directionMayInvert && this.invertDirection) { if (line.directionMayInvert && this.invertDirection) {
isNorth = !isNorth; isNorth = !isNorth;
} }
Route route = new Route(); Route route = new Route();
route.setOrigin(this); route.setOrigin(origin);
route.setDestination(dest); route.setDirectLine(line);
if (this.equals(origin)) {
route.setDestination(dest);
} else {
// This must be the outbound transfer station
route.setDestination(origin.getOutboundTransferStation());
route.setTransferLines(transferLines);
}
route.setDirection(isNorth ? "n" : "s"); route.setDirection(isNorth ? "n" : "s");
route.setLine(line);
if (transferStation != null || line.requiresTransfer) { if (transferStation != null || line.requiresTransfer) {
route.setTransfer(true); route.setTransfer(true);
} else { } else {
route.setTransfer(false); route.setTransfer(false);
} }
if (route.hasTransfer() && !transferFriendly
&& !Line.YELLOW_ORANGE_SCHEDULED_TRANSFER.equals(line)) {
continue;
}
returnList.add(route); returnList.add(route);
} }
if (isNorth == null) { return returnList;
if (outboundTransferStation != null) { }
returnList.addAll(getOutboundTransferStation()
.getRoutesForDestination(dest, public List<Route> getTransferRoutes(Station dest) {
getOutboundTransferStation())); List<Route> returnList = new ArrayList<Route>();
} else if (dest.getInboundTransferStation() != null) { if (dest.getInboundTransferStation() != null) {
final List<Route> routesForDestination = getRoutesForDestination( // Try getting to the destination's inbound xfer station first
dest.getInboundTransferStation(), returnList.addAll(getDirectRoutesForDestination(this,
dest.getInboundTransferStation()); dest.getInboundTransferStation(),
if (routesForDestination != null dest.getInboundTransferStation(), null));
&& !routesForDestination.isEmpty()) { }
returnList.addAll(routesForDestination);
} if (returnList.isEmpty() && outboundTransferStation != null) {
// Try getting from the outbound transfer station to the
// destination next
final Collection<Line> outboundTransferLines = Line
.getLinesWithStations(this, getOutboundTransferStation());
final List<Route> routesForDestination = getOutboundTransferStation()
.getDirectRoutesForDestination(this, dest,
getOutboundTransferStation(), outboundTransferLines);
if (routesForDestination != null && !routesForDestination.isEmpty()) {
returnList.addAll(routesForDestination);
} }
} }
if (returnList.isEmpty()) {
// Try getting from the outbound transfer station to the
// destination's inbound xfer station
final List<Route> routesForDestination = getDoubleTransferRoutes(dest);
if (routesForDestination != null && !routesForDestination.isEmpty()) {
returnList.addAll(routesForDestination);
}
}
return returnList; return returnList;
} }
public List<Route> getDoubleTransferRoutes(Station dest) {
if (getOutboundTransferStation() == null
|| dest.getInboundTransferStation() == null)
return new ArrayList<Route>();
// Get routes from the outbound transfer station to the
// destination's inbound xfer station
return getOutboundTransferStation().getDirectRoutesForDestination(this,
dest.getInboundTransferStation(), getOutboundTransferStation(),
Line.getLinesWithStations(this, getOutboundTransferStation()));
}
static public List<Station> getStationList() { static public List<Station> getStationList() {
List<Station> list = new ArrayList<Station>(); List<Station> list = new ArrayList<Station>();
for (Station station : values()) { for (Station station : values()) {

View File

@ -40,9 +40,14 @@ public abstract class GetRealTimeDeparturesTask extends
// Always expect one param // Always expect one param
StationPair params = paramsArray[0]; StationPair params = paramsArray[0];
mRoutes = params.getOrigin().getRoutesForDestination( mRoutes = params.getOrigin().getDirectRoutesForDestination(
params.getDestination()); params.getDestination());
if (mRoutes.isEmpty() || params.getOrigin().transferFriendly) {
mRoutes.addAll(params.getOrigin().getTransferRoutes(
params.getDestination()));
}
if (!isCancelled()) { if (!isCancelled()) {
return getDeparturesFromNetwork(params, 0); return getDeparturesFromNetwork(params, 0);
} else { } else {

View File

@ -24,7 +24,7 @@ public abstract class GetScheduleInformationTask extends
AsyncTask<StationPair, Integer, ScheduleInformation> { AsyncTask<StationPair, Integer, ScheduleInformation> {
private final static String SCHED_URL = "http://api.bart.gov/api/sched.aspx?cmd=depart&key=" private final static String SCHED_URL = "http://api.bart.gov/api/sched.aspx?cmd=depart&key="
+ Constants.API_KEY + "&orig=%1$s&dest=%2$s&b=1&a=5"; + Constants.API_KEY + "&orig=%1$s&dest=%2$s&b=1&a=4";
private final static int MAX_ATTEMPTS = 5; private final static int MAX_ATTEMPTS = 5;