Beispiel #1
0
def write_ride(ride_id, team=None):
    """
    Takes the specified ride_id and merges together the V1 and V2 API data into model 
    objects and writes them to the database.
    
    :param ride_id: The ride that should be filled in and written to DB.
    :type ride_id: int
    
    :param team: The team club entity.
    :type team: :class:`stravatools.bafs.model.Club`
    
    :return: The written Ride object.
    """
    v1sess = V1ServerProxy()
    v2sess = V2ServerProxy()

    v1data = v1sess.get_ride(ride_id)
    v2data = v2sess.get_ride(ride_id)

    # logger().info(repr(v2data))

    if v2data["start_latlng"]:
        (lat, lon) = v2data["start_latlng"]
        start_geo = WKTSpatialElement("POINT({lat} {lon})".format(lat=lat, lon=lon))
    else:
        start_geo = None

    if v2data["end_latlng"]:
        (lat, lon) = v2data["end_latlng"]
        end_geo = WKTSpatialElement("POINT({lat} {lon})".format(lat=lat, lon=lon))
    else:
        end_geo = None

    athlete_id = v1data["athlete"]["id"]

    # In the BAFS model, an athlete only belongs to a single team club (at most - there are a few unclubbed riders)
    athlete = Athlete(id=athlete_id, team=team, name=v1data["athlete"]["name"])

    db.session.merge(athlete)  # @UndefinedVariable
    db.session.commit()  # @UndefinedVariable

    if start_geo is not None or end_geo is not None:
        ride_geo = RideGeo()
        ride_geo.start_geo = start_geo
        ride_geo.end_geo = end_geo
        ride_geo.ride_id = v2data["id"]
        db.session.merge(ride_geo)  # @UndefinedVariable

    try:
        ride = Ride(
            id=v2data["id"],
            athlete=athlete,
            name=v2data["name"],
            start_date=parser.parse(v2data["start_date_local"]).replace(tzinfo=None),
            distance=units.meters_to_miles(v2data["distance"]),
            average_speed=units.metersps_to_mph(v1data["averageSpeed"]),
            maximum_speed=units.kph_to_mph(
                v1data["maximumSpeed"] / 1000.0
            ),  # Not sure why this is in meters per hour ... !?
            elapsed_time=v2data["elapsed_time"],
            moving_time=v2data["moving_time"],
            location=v2data.get("location"),
            commute=v1data["commute"],
            trainer=v1data["trainer"],
            elevation_gain=units.meters_to_feet(v2data["elevation_gain"]),
        )

        db.session.merge(ride)  # @UndefinedVariable

        logger().debug(
            'Writing ride: {athlete!r}: "{ride!r}" on {date}'.format(
                athlete=athlete.name, ride=ride.name, date=ride.start_date.strftime("%m/%d/%y")
            )
        )
        db.session.commit()  # @UndefinedVariable
    except:
        logger().exception("Error adding ride: {0}".format(ride_id))
        raise

    return ride
Beispiel #2
0
def write_ride(activity):
    """
    Takes the specified activity and writes it to the database.

    :param activity: The Strava :class:`stravalib.model.Activity` object.
    :type activity: stravalib.model.Activity

    :return: A tuple including the written Ride model object, whether to resync segment efforts, and whether to resync photos.
    :rtype: bafs.model.Ride
    """

    if activity.start_latlng:
        start_geo = WKTSpatialElement('POINT({lon} {lat})'.format(lat=activity.start_latlng.lat,
                                                                  lon=activity.start_latlng.lon))
    else:
        start_geo = None

    if activity.end_latlng:
        end_geo = WKTSpatialElement('POINT({lon} {lat})'.format(lat=activity.end_latlng.lat,
                                                                lon=activity.end_latlng.lon))
    else:
        end_geo = None

    athlete_id = activity.athlete.id

    # Fail fast for invalid data (this can happen with manual-entry rides)
    assert activity.elapsed_time is not None
    assert activity.moving_time is not None
    assert activity.distance is not None

    # Find the model object for that athlete (or create if doesn't exist)
    athlete = db.session.query(Athlete).get(athlete_id)
    if not athlete:
        # The athlete has to exist since otherwise we wouldn't be able to query their rides
        raise ValueError("Somehow you are attempting to write rides for an athlete not found in the database.")

    if start_geo is not None or end_geo is not None:
        ride_geo = RideGeo()
        ride_geo.start_geo = start_geo
        ride_geo.end_geo = end_geo
        ride_geo.ride_id = activity.id
        db.session.merge(ride_geo)

    ride = db.session.query(Ride).get(activity.id)
    new_ride = (ride is None)
    if ride is None:
        ride = Ride(activity.id)

    # Check to see if we need to pull down efforts for this ride
    if new_ride:
        ride.detail_fetched = False  # Just to be explicit

        if not activity.manual:
            ride.track_fetched = False

        # photo_count refers to instagram photos
        if activity.photo_count > 1:
            ride.photos_fetched = False
        else:
            ride.photos_fetched = None

    else:
        if round(ride.distance, 2) != round(float(unithelper.miles(activity.distance)), 2):
            log.info("Queing resync of details for activity {0!r}: distance mismatch ({1} != {2})".format(activity,
                                                                                                          ride.distance,
                                                                                                          unithelper.miles(activity.distance)))
            ride.detail_fetched = False
            ride.track_fetched = False

    ride.athlete = athlete


    update_ride_from_activity(strava_activity=activity, ride=ride)


    db.session.add(ride)

    return ride
Beispiel #3
0
def write_ride(activity):
    """
    Takes the specified activity and writes it to the database.

    :param activity: The Strava :class:`stravalib.model.Activity` object.
    :type activity: stravalib.model.Activity

    :return: A tuple including the written Ride model object, whether to resync segment efforts, and whether to resync photos.
    :rtype: bafs.model.Ride
    """

    if activity.start_latlng:
        start_geo = WKTSpatialElement('POINT({lon} {lat})'.format(lat=activity.start_latlng.lat,
                                                                  lon=activity.start_latlng.lon))
    else:
        start_geo = None

    if activity.end_latlng:
        end_geo = WKTSpatialElement('POINT({lon} {lat})'.format(lat=activity.end_latlng.lat,
                                                                lon=activity.end_latlng.lon))
    else:
        end_geo = None

    athlete_id = activity.athlete.id

    # Fail fast for invalid data (this can happen with manual-entry rides)
    assert activity.elapsed_time is not None
    assert activity.moving_time is not None
    assert activity.distance is not None

    # Find the model object for that athlete (or create if doesn't exist)
    athlete = db.session.query(Athlete).get(athlete_id)
    if not athlete:
        # The athlete has to exist since otherwise we wouldn't be able to query their rides
        raise ValueError("Somehow you are attempting to write rides for an athlete not found in the database.")

    if start_geo is not None or end_geo is not None:
        ride_geo = RideGeo()
        ride_geo.start_geo = start_geo
        ride_geo.end_geo = end_geo
        ride_geo.ride_id = activity.id
        db.session.merge(ride_geo)

    ride = db.session.query(Ride).get(activity.id)
    new_ride = (ride is None)
    if ride is None:
        ride = Ride(activity.id)

    # Check to see if we need to pull down efforts for this ride
    if new_ride:
        ride.detail_fetched = False  # Just to be explicit

        if not activity.manual:
            ride.track_fetched = False

        # photo_count refers to instagram photos
        if activity.photo_count > 1:
            ride.photos_fetched = False
        else:
            ride.photos_fetched = None

    else:
        if round(ride.distance, 2) != round(float(unithelper.miles(activity.distance)), 2):
            log.info("Queing resync of details for activity {0!r}: distance mismatch ({1} != {2})".format(activity,
                                                                                                          ride.distance,
                                                                                                          unithelper.miles(activity.distance)))
            ride.detail_fetched = False
            ride.track_fetched = False

    ride.athlete = athlete


    update_ride_from_activity(strava_activity=activity, ride=ride)


    db.session.add(ride)

    return ride