Example #1
0
def _request_search( **kwargs ):
    '''
    Searches for RideRequests that meet the criteria specified in **kargs.
    The criteria are:

    REQUIRED:
    polygon : a list of coordinates giving the route of the offer
    date : a datetime object giving the departure date and time
    fuzziness : the time fuzziness to search within

    NOT REQUIRED:
    other_filters : a dictionary containing other filters to apply in the query

    Returns a list of RideOffers that match

    '''
    polygon = kwargs['polygon']
    offer_start_time = kwargs['date']
    offer_fuzziness = kwargs['fuzziness']

    # RideRequests within the bounds
    if not 'other_filters' in kwargs:
        requests_within_start = RideRequest.objects.filter( start__position__within_polygon=polygon )
    else:
        requests_within_start = RideRequest.objects.filter( start__position__within_polygon=polygon,
                                                            **kwargs['other_filters'] )

    # Filter by date
    def in_date( req ):
        return _dates_match( req.date, req.fuzziness, offer_start_time, offer_fuzziness )
    requests_within_start = [req for req in requests_within_start if in_date(req)]

    # Can't do two geospatial queries at once :(
    bboxArea = Polygon( polygon )
    requests_on_route = [r for r in requests_within_start if bboxArea.isInside(*r.end.position)]
    return requests_on_route
Example #2
0
def _offer_search( **kwargs ):
    '''
    Searches for RideOffers that meet the criteria specified in **kargs.
    The criteria are:

    REQUIRED:
    start_lat : the starting latitude of the request
    start_lng : the starting longitude of the request
    end_lat
    end_lng
    date : a datetime object giving the departure date and time
    fuzziness : the fuzziness (time range) to search with

    NOT REQUIRED:
    other_filters : a dictionary containing other filters to apply in the query

    Returns a list of RideOffers that match
    '''

    # Find all offers that match our time constraints
    request_date = kwargs['date']
    request_fuzzy = kwargs['fuzziness']
    if '-' in request_fuzzy:
        delta = timedelta(hours=int(request_fuzzy.split('-')[0]))
        earliest_offer = request_date - delta
        latest_offer = request_date + delta
    elif request_fuzzy == 'day':
        earliest_offer = datetime(request_date.year, request_date.month, request_date.day)
        next_day = request_date + timedelta(days=1)
        latest_offer = datetime(next_day.year, next_day.month, next_day.day)
    elif request_fuzzy == 'week':
        delta = timedelta(days=3, hours=12)
        earliest_offer = request_date - delta
        latest_offer = request_date + delta

    if 'other_filters' in kwargs:
        if request_fuzzy == 'anytime':
            offers = RideOffer.objects.filter( **kwargs['other_filters'] )
        else:
            offers = RideOffer.objects.filter( date__gte=earliest_offer,
                                               date__lte=latest_offer,
                                               **kwargs['other_filters'] )
    else:
        if request_fuzzy == 'anytime':
            offers = RideOffer.objects.all()
        else:
            offers = RideOffer.objects.filter( date__gte=earliest_offer,
                                               date__lte=latest_offer )

    # Filter offers further:
    # 1. Must have start point near req. start and end point near req. end --OR--
    # 2. Must have polygon field that overlays start & end of this request
    filtered_offers = []
    for offer in offers:
        # Results might be less fuzzy than we are, so do some checking here
        if not _dates_match( offer.date, offer.fuzziness, request_date, request_fuzzy ):
            continue
        # Geographical constraints
        req_start = (float(kwargs['start_lat']),
                     float(kwargs['start_lng']))
        req_end = (float(kwargs['end_lat']),
                   float(kwargs['end_lng']))
        start_dist = geospatial_distance( offer.start.position, req_start )
        end_dist = geospatial_distance( offer.end.position, req_end )
        if start_dist < 5 and end_dist < 5:
            filtered_offers.append( offer )
        elif len(offer.polygon) > 0:
            polygon = Polygon( offer.polygon )
            if polygon.isInside( *req_start ) and polygon.isInside( *req_end ):
                filtered_offers.append( offer )
    return filtered_offers