package org.croudtrip.trips; import org.croudtrip.api.directions.NavigationResult; import org.croudtrip.api.directions.Route; import org.croudtrip.api.directions.RouteLocation; import org.croudtrip.api.trips.JoinTripRequest; import org.croudtrip.api.trips.TripOffer; import org.croudtrip.api.trips.TripQuery; import org.croudtrip.api.trips.UserWayPoint; import org.croudtrip.db.JoinTripRequestDAO; import org.croudtrip.directions.DirectionsManager; import org.croudtrip.directions.RouteNotFoundException; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; /** * Handles all navigation / time of arrival tasks which are directly * related to a {@link org.croudtrip.api.trips.TripOffer}. * Unlike {@link org.croudtrip.directions.DirectionsManager}, this * class is not responsible for any low level navigation. */ public class TripsNavigationManager { private final TspSolver tspSolver; private final JoinTripRequestDAO joinTripRequestDAO; private final DirectionsManager directionsManager; @Inject public TripsNavigationManager( TspSolver tspSolver, JoinTripRequestDAO joinTripRequestDAO, DirectionsManager directionsManager) { this.tspSolver = tspSolver; this.joinTripRequestDAO = joinTripRequestDAO; this.directionsManager = directionsManager; } public List<UserWayPoint> getRouteWaypointsForOffer(TripOffer offer) { return getRouteWaypointsForOffer(offer, null); } /** * Returns the complete route waypoints for a given {@link TripOffer} * and one {@link TripQuery} including all passenger way points and their expected * arrival time. * @param offer the offer which includes the driver route and which is used to find * the pending {@link org.croudtrip.api.trips.JoinTripRequest}. * @param query an optional query which should also be considered during the matching * process. */ public List<UserWayPoint> getRouteWaypointsForOffer(TripOffer offer, TripQuery query) { List<JoinTripRequest> joinTripRequests = joinTripRequestDAO.findByOfferId(offer.getId()); List<TspSolver.TspWayPoint> tspWayPoints; if (query == null) { tspWayPoints = tspSolver.getBestOrder(joinTripRequests, offer) .get(0); } else { tspWayPoints = tspSolver.getBestOrder(joinTripRequests, offer, query) .get(0); } List<RouteLocation> passengerLocations = new ArrayList<>(); for (int i = 1; i < tspWayPoints.size() - 1; ++i) { passengerLocations.add(tspWayPoints.get(i).getLocation()); } List<Route> routes = directionsManager.getDirections( offer.getDriverRoute().getWayPoints().get(0), offer.getDriverRoute().getWayPoints().get(1), passengerLocations); if (routes == null || routes.isEmpty()) return new ArrayList<>(); List<UserWayPoint> userWayPoints = new ArrayList<>(); long arrivalTimestamp = System.currentTimeMillis() / 1000; long distanceToDriverInMeters = 0; for (int i = 0; i < tspWayPoints.size(); ++i) { if (i != 0) { arrivalTimestamp += routes.get(0).getLegDurationsInSeconds().get(i - 1); distanceToDriverInMeters += routes.get(0).getLegDistancesInMeters().get(i - 1); } TspSolver.TspWayPoint tspWayPoint = tspWayPoints.get(i); userWayPoints.add(new UserWayPoint( tspWayPoint.getUser(), tspWayPoint.getLocation(), tspWayPoint.isStart(), arrivalTimestamp, distanceToDriverInMeters)); } return userWayPoints; } /** * Returns the {@link org.croudtrip.api.directions.NavigationResult} * for a given {@link TripOffer} with an optimal solution for visiting all the passengers * @param offer the offer you want to do the navigation request for. * @return the navigation result for this offer. * @throws RouteNotFoundException If there exists no route for the driver. */ public NavigationResult getNavigationResultForOffer(TripOffer offer) throws RouteNotFoundException { return getNavigationResultForOffer( offer, null ); } /** * Returns the {@link org.croudtrip.api.directions.NavigationResult} * for a given {@link TripOffer} with an optimal solution for visiting all the passengers * @param offer the offer you want to do the navigation request for. * @param query an optional query which should also be considered during the matching process. * @return the navigation result for this offer. * @throws RouteNotFoundException If there exists no route for the driver. */ public NavigationResult getNavigationResultForOffer(TripOffer offer, TripQuery query) throws RouteNotFoundException { List<TspSolver.TspWayPoint> tspWayPoints; if( query != null ) tspWayPoints = tspSolver.getBestOrder( joinTripRequestDAO.findByOfferId(offer.getId()), offer, query).get(0); else tspWayPoints = tspSolver.getBestOrder( joinTripRequestDAO.findByOfferId(offer.getId()), offer).get(0); List<RouteLocation> passengerLocations = new ArrayList<>(); for (int i = 1; i < tspWayPoints.size() - 1; ++i) { passengerLocations.add(tspWayPoints.get(i).getLocation()); } List<Route> routes = directionsManager.getDirections( offer.getDriverRoute().getWayPoints().get(0), offer.getDriverRoute().getWayPoints().get(1), passengerLocations); if (routes == null || routes.isEmpty()) throw new RouteNotFoundException(); List<UserWayPoint> userWayPoints = new ArrayList<>(); long arrivalTimestamp = System.currentTimeMillis() / 1000; long distanceToDriverInMeters = 0; for (int i = 0; i < tspWayPoints.size(); ++i) { if (i != 0) { arrivalTimestamp += routes.get(0).getLegDurationsInSeconds().get(i - 1); distanceToDriverInMeters += routes.get(0).getLegDistancesInMeters().get(i - 1); } TspSolver.TspWayPoint tspWayPoint = tspWayPoints.get(i); userWayPoints.add(new UserWayPoint( tspWayPoint.getUser(), tspWayPoint.getLocation(), tspWayPoint.isStart(), arrivalTimestamp, distanceToDriverInMeters)); } return new NavigationResult( routes.get(0), userWayPoints ); } }