/*
* Copyright (C) 2014 Jason M. Heim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jasonmheim.rollout.station;
import android.location.Location;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
import com.jasonmheim.rollout.action.ActionManager;
import com.jasonmheim.rollout.data.DestinationDistanceCalculator;
import com.jasonmheim.rollout.data.Station;
import com.jasonmheim.rollout.data.StationDistance;
import com.jasonmheim.rollout.data.StationDistanceCalculator;
import com.jasonmheim.rollout.data.StationDistanceRank;
import com.jasonmheim.rollout.data.StationList;
import com.jasonmheim.rollout.location.LocationManager;
import com.jasonmheim.rollout.settings.Settings;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import static com.jasonmheim.rollout.Constants.ACTION_RIDE;
/**
* Station data utility class, handles sorting and threshold data based on the current action,
* location, and other settings.
*/
@Singleton
public class StationDataProcessor {
private final ActionManager actionManager;
private final LocationManager locationManager;
private final Settings settings;
@Inject
public StationDataProcessor(
ActionManager actionManager,
LocationManager locationManager,
Settings settings) {
this.actionManager = actionManager;
this.locationManager = locationManager;
this.settings = settings;
}
/**
* Converts the given {@code stationList} to a list of {@link com.jasonmheim.rollout.data.StationDistance} instances which
* are sorted by distance. If the current action is riding, and a destination is specified, then
* these are sorted by proximity to the destination, with additional weight given to the user's
* current location. Otherwise the results are sorted by proximity to the user's current location.
*/
public List<StationDistance> orderClosestStations(StationList stationList) {
if (stationList == null) {
return Collections.emptyList();
}
return orderClosestStations(stationList, actionManager.getAction());
}
/**
* Takes the given {@code stationList} and searches for the station that best suits the user's
* current needs. The stations are ordered as described in {@link #orderClosestStations}. If the
* user is currently riding, the first station with available docks is returned. Otherwise the
* first station with available bikes is returned.
*/
public StationDistanceRank getClosestAvailableStation(StationList stationList) {
int action = actionManager.getAction();
List<StationDistance> orderedStations = orderClosestStations(stationList, action);
if (action == ACTION_RIDE) {
return getClosestStationWithDocks(orderedStations, settings.getFullThreshold());
}
return getClosestStationWithBikes(orderedStations, settings.getEmptyThreshold());
}
private StationDistanceRank getClosestStationWithDocks(
List<StationDistance> orderedStations, int docks) {
int rank = 0;
for (StationDistance stationDistance : orderedStations) {
if (stationDistance.getStation().availableDocks > docks) {
return new StationDistanceRank(stationDistance, rank);
}
rank++;
}
return null;
}
private StationDistanceRank getClosestStationWithBikes(
List<StationDistance> orderedStations, int bikes) {
int rank = 0;
for (StationDistance stationDistance : orderedStations) {
if (stationDistance.getStation().availableBikes > bikes) {
return new StationDistanceRank(stationDistance, rank);
}
rank++;
}
return null;
}
private List<StationDistance> orderClosestStations(StationList stationList, int action) {
if (stationList == null) {
return Collections.emptyList();
}
Location location = locationManager.getLastLocation();
if (location != null) {
Location destination = actionManager.getDestination();
Function<Station, ? extends StationDistance> calculator;
if (action == ACTION_RIDE && destination != null) {
calculator = new DestinationDistanceCalculator(
location.getLatitude(), location.getLongitude(),
destination.getLatitude(), destination.getLongitude());
} else {
calculator = new StationDistanceCalculator(location.getLatitude(), location.getLongitude());
}
return Ordering.natural().immutableSortedCopy(
Iterables.transform(stationList.stationBeanList, calculator));
}
return Collections.emptyList();
}
}