package com.schneeloch.bostonbusmap_library.data; import java.io.IOException; import java.util.Collection; import java.util.Set; import java.util.SortedSet; import com.schneeloch.bostonbusmap_library.transit.TransitSystem; import com.schneeloch.bostonbusmap_library.util.LogUtil; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.Sets; /** * Immutable view of prediction information, for sharing between threads * @author schneg * */ public class StopPredictionViewImpl extends StopPredictionView { private final String snippetTitle; private final String[] titles; private final String[] routeTitles; private final String stops; private final String places; private final String snippet; private final IPrediction[] predictions; private final ImmutableCollection<Alert> alerts; /** * Note that this makes defensive copies of all containers. It doesn't use ImmutableList * because Parcelables use arrays when transferring data * @param stops * @param ifOnlyOneRoute * @param routeKeysToTitles * @param alerts */ public StopPredictionViewImpl(Set<String> routeTags, Collection<StopLocation> stops, SortedSet<IPrediction> predictions, RouteConfig ifOnlyOneRoute, RouteTitles routeKeysToTitles, ImmutableCollection<Alert> alerts, Locations locations) { Set<String> stopTitles = Sets.newTreeSet(); SortedSet<String> stopIds = Sets.newTreeSet(); int allCount = 0; int someCount = 0; int noneCount = 0; SortedSet<String> places = Sets.newTreeSet(); for (StopLocation stop : stops) { stopTitles.add(stop.getTitle()); stopIds.add(stop.getStopTag()); if (stop.getParent().isPresent()) { places.add(stop.getParent().get()); } Updated updated = stop.wasEverUpdated(ifOnlyOneRoute); if (updated == Updated.All) { allCount++; } else if (updated == Updated.Some) { someCount++; } else if (updated == Updated.None) { noneCount++; } } Updated updated; if (noneCount > 0 && allCount == 0 && someCount == 0) { updated = Updated.None; } else if (allCount > 0 && noneCount == 0 && someCount == 0) { updated = Updated.All; } else { updated = Updated.Some; } snippetTitle = makeSnippetTitle(stopTitles); SortedSet<String> routeTitles = Sets.newTreeSet(new RouteTitleComparator()); for (String tag : routeTags) { String title = routeKeysToTitles.getTitle(tag); routeTitles.add(title); } this.routeTitles = routeTitles.toArray(nullStrings); this.titles = stopTitles.toArray(nullStrings); this.alerts = alerts; StringBuilder ret = new StringBuilder(); try { SortedSet<String> routeTitlesNotRunning = Sets.newTreeSet(); for (String routeTag : routeTags) { RouteConfig route = locations.getRoute(routeTag); if (route.isRouteRunning() == false) { routeTitlesNotRunning.add(routeKeysToTitles.getTitle(routeTag)); } } /* if (routeTitlesNotRunning.size() == 1) { String routeTitle = routeTitlesNotRunning.first(); ret.append("<font size='1'>Route " + routeTitle + " is not currently running").append("</font><br />"); } else if (routeTitlesNotRunning.size() > 1) { String routeTitle = Joiner.on(", ").join(routeTitlesNotRunning); ret.append("<font size='1'>Routes " + routeTitle + " are not currently running</font><br />"); }*/ } catch (IOException e) { LogUtil.e(e); } makeSnippet(ifOnlyOneRoute, predictions, updated, ret); snippet = ret.toString(); this.stops = Joiner.on(", ").join(stopIds); this.places = Joiner.on(", ").join(places); this.predictions = predictions.toArray(nullPredictions); } private String makeSnippetTitle(Collection<String> titles) { StringBuilder ret = new StringBuilder(); int count = 0; for (String title : titles) { if (count >= 1) { ret.append(", ..."); break; } else { ret.append(title); } count++; } return ret.toString(); } private static void makeSnippet(RouteConfig routeConfig, Collection<IPrediction> predictions, Updated hasUpdated, StringBuilder ret) { if (predictions == null || predictions.isEmpty()) { if (hasUpdated == Updated.All) { ret.append("No predictions for this stop"); } else if (hasUpdated == Updated.None) { ret.append("No information received yet for this stop"); } else if (hasUpdated == Updated.Some) { ret.append("Some information not received yet for this stop"); } return; } final int max = 3; int count = 0; for (IPrediction prediction : predictions) { if (routeConfig != null && routeConfig.getRouteName().equals(prediction.getRouteName()) == false) { continue; } if (prediction.isInvalid()) { continue; } if (count != 0) { ret.append("<br />"); } ret.append("<br />"); prediction.makeSnippet(ret, TransitSystem.showRunNumber()); count++; if (count >= max) { break; } } } @Override public String[] getTitles() { return titles; } @Override public String[] getRouteTitles() { return routeTitles; } @Override public String getStops() { return stops; } @Override public String getPlaces() { return places; } @Override public String getSnippet() { return snippet; } @Override public String getSnippetTitle() { return snippetTitle; } /** * Do not modify this! */ @Override public IPrediction[] getPredictions() { return predictions; } @Override public ImmutableCollection<Alert> getAlerts() { return alerts; } }