strava-ruby-client 3.0.0.pre.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -2
- data/README.md +47 -58
- data/lib/strava/api/client.rb +69 -0
- data/lib/strava/api/config.rb +40 -0
- data/lib/strava/api/cursor.rb +32 -1
- data/lib/strava/api/endpoints/activities.rb +197 -57
- data/lib/strava/api/endpoints/athletes.rb +64 -8
- data/lib/strava/api/endpoints/clubs.rb +24 -59
- data/lib/strava/api/endpoints/gears.rb +11 -2
- data/lib/strava/api/endpoints/oauth.rb +45 -0
- data/lib/strava/api/endpoints/routes.rb +20 -13
- data/lib/strava/api/endpoints/segment_efforts.rb +15 -8
- data/lib/strava/api/endpoints/segments.rb +74 -21
- data/lib/strava/api/endpoints/streams.rb +22 -18
- data/lib/strava/api/endpoints/uploads.rb +12 -2
- data/lib/strava/api/pagination.rb +25 -0
- data/lib/strava/api/ratelimit.rb +34 -0
- data/lib/strava/deep_copyable.rb +20 -1
- data/lib/strava/errors/fault.rb +32 -0
- data/lib/strava/errors/ratelimit_error.rb +35 -0
- data/lib/strava/errors/upload_error.rb +55 -0
- data/lib/strava/logger.rb +27 -0
- data/lib/strava/models/achievement.rb +28 -1
- data/lib/strava/models/activity_stats.rb +47 -1
- data/lib/strava/models/activity_total.rb +25 -1
- data/lib/strava/models/activity_zone.rb +39 -2
- data/lib/strava/models/authorization.rb +13 -0
- data/lib/strava/models/base_stream.rb +22 -1
- data/lib/strava/models/club_event.rb +64 -1
- data/lib/strava/models/comment.rb +39 -1
- data/lib/strava/models/destination.rb +28 -1
- data/lib/strava/models/detailed_activity.rb +203 -2
- data/lib/strava/models/detailed_athlete.rb +104 -2
- data/lib/strava/models/detailed_club.rb +76 -2
- data/lib/strava/models/detailed_gear.rb +45 -2
- data/lib/strava/models/detailed_photo.rb +61 -1
- data/lib/strava/models/detailed_photos.rb +29 -1
- data/lib/strava/models/detailed_segment.rb +89 -2
- data/lib/strava/models/detailed_segment_effort.rb +92 -3
- data/lib/strava/models/explorer_segment.rb +55 -2
- data/lib/strava/models/heart_rate_zone_ranges.rb +29 -1
- data/lib/strava/models/kudoser.rb +29 -1
- data/lib/strava/models/lap.rb +62 -2
- data/lib/strava/models/lat_lng.rb +42 -4
- data/lib/strava/models/local_legend.rb +41 -1
- data/lib/strava/models/map.rb +31 -0
- data/lib/strava/models/meta_activity.rb +15 -2
- data/lib/strava/models/meta_athlete.rb +17 -2
- data/lib/strava/models/meta_club.rb +15 -1
- data/lib/strava/models/mixins/average_speed.rb +81 -3
- data/lib/strava/models/mixins/distance.rb +25 -0
- data/lib/strava/models/mixins/elapsed_time.rb +18 -0
- data/lib/strava/models/mixins/elevation_difference.rb +42 -0
- data/lib/strava/models/mixins/elevation_gain.rb +39 -0
- data/lib/strava/models/mixins/estimated_moving_time.rb +18 -0
- data/lib/strava/models/mixins/http_response.rb +36 -0
- data/lib/strava/models/mixins/moving_time.rb +18 -0
- data/lib/strava/models/mixins/sport_type.rb +39 -1
- data/lib/strava/models/mixins/start_date_local.rb +40 -24
- data/lib/strava/models/mixins/time_in_hours.rb +23 -0
- data/lib/strava/models/mixins/total_elevation_gain.rb +42 -0
- data/lib/strava/models/model.rb +14 -0
- data/lib/strava/models/photos_summary.rb +26 -2
- data/lib/strava/models/photos_summary_primary.rb +28 -2
- data/lib/strava/models/power_zone_ranges.rb +23 -1
- data/lib/strava/models/response.rb +18 -0
- data/lib/strava/models/route.rb +63 -2
- data/lib/strava/models/similar_activities.rb +57 -1
- data/lib/strava/models/split.rb +27 -2
- data/lib/strava/models/stats_visibility.rb +24 -1
- data/lib/strava/models/stream.rb +107 -0
- data/lib/strava/models/stream_set.rb +52 -1
- data/lib/strava/models/summary_activity.rb +145 -2
- data/lib/strava/models/summary_athlete.rb +54 -1
- data/lib/strava/models/summary_club.rb +61 -2
- data/lib/strava/models/summary_gear.rb +31 -2
- data/lib/strava/models/summary_pr_segment_effort.rb +32 -2
- data/lib/strava/models/summary_segment.rb +80 -2
- data/lib/strava/models/summary_segment_effort.rb +32 -1
- data/lib/strava/models/timed_zone_range.rb +24 -1
- data/lib/strava/models/token.rb +31 -0
- data/lib/strava/models/trend.rb +38 -1
- data/lib/strava/models/updatable_activity.rb +36 -1
- data/lib/strava/models/upload.rb +50 -1
- data/lib/strava/models/waypoint.rb +31 -1
- data/lib/strava/models/xoms.rb +35 -1
- data/lib/strava/models/zone_range.rb +20 -1
- data/lib/strava/models/zones.rb +32 -1
- data/lib/strava/oauth/client.rb +107 -19
- data/lib/strava/oauth/config.rb +41 -0
- data/lib/strava/version.rb +1 -1
- data/lib/strava/web/api_response.rb +28 -2
- data/lib/strava/web/client.rb +72 -2
- data/lib/strava/web/config.rb +40 -0
- data/lib/strava/web/connection.rb +39 -0
- data/lib/strava/web/raise_response_error.rb +47 -0
- data/lib/strava/web/request.rb +56 -0
- data/lib/strava/web/response.rb +18 -0
- data/lib/strava/webhooks/client.rb +108 -7
- data/lib/strava/webhooks/config.rb +44 -0
- data/lib/strava/webhooks/models/challenge.rb +40 -0
- data/lib/strava/webhooks/models/event.rb +50 -0
- data/lib/strava/webhooks/models/subscription.rb +27 -0
- data/lib/strava-ruby-client.rb +0 -2
- metadata +2 -4
- data/lib/strava/models/club_activity.rb +0 -22
- data/lib/strava/models/club_athlete.rb +0 -21
|
@@ -2,28 +2,88 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents a photo or video attached to an activity.
|
|
7
|
+
#
|
|
8
|
+
# Photos can be uploaded directly to Strava or linked from Instagram.
|
|
9
|
+
# This model contains URLs to various sizes of the media, timestamps,
|
|
10
|
+
# and metadata about the photo or video.
|
|
11
|
+
#
|
|
12
|
+
# Note: This is an undocumented Strava API endpoint.
|
|
13
|
+
#
|
|
14
|
+
# @example List activity photos
|
|
15
|
+
# photos = client.activity_photos(1234567890)
|
|
16
|
+
# photos.each do |photo|
|
|
17
|
+
# puts photo.caption if photo.caption
|
|
18
|
+
# puts "Uploaded: #{photo.uploaded_at}"
|
|
19
|
+
# puts "URL: #{photo.urls['0']}" if photo.urls
|
|
20
|
+
# puts "Video: #{photo.video_url}" if photo.video_url
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# @see Strava::Api::Client#activity_photos
|
|
24
|
+
#
|
|
6
25
|
class DetailedPhoto < Strava::Models::Response
|
|
26
|
+
# @return [String] Unique identifier for the photo/video
|
|
7
27
|
property 'unique_id'
|
|
28
|
+
|
|
29
|
+
# @return [Integer] ID of the athlete who uploaded the photo
|
|
8
30
|
property 'athlete_id'
|
|
31
|
+
|
|
32
|
+
# @return [Integer] ID of the activity this photo is attached to
|
|
9
33
|
property 'activity_id'
|
|
34
|
+
|
|
35
|
+
# @return [String] Name of the activity
|
|
10
36
|
property 'activity_name'
|
|
37
|
+
|
|
38
|
+
# @return [Integer, nil] Post identifier if photo is from a social post
|
|
11
39
|
property 'post_id'
|
|
40
|
+
|
|
41
|
+
# @return [Integer] Resource state indicator
|
|
12
42
|
property 'resource_state'
|
|
43
|
+
|
|
44
|
+
# @return [String, nil] Photo caption/description
|
|
13
45
|
property 'caption'
|
|
46
|
+
|
|
47
|
+
# @return [Integer] Type of media (1=photo, 2=video)
|
|
14
48
|
property 'type'
|
|
49
|
+
|
|
50
|
+
# @return [Integer] Source of the photo (1=native Strava upload, 2=Instagram)
|
|
15
51
|
property 'source'
|
|
52
|
+
|
|
53
|
+
# @return [String] Processing status
|
|
16
54
|
property 'status'
|
|
55
|
+
|
|
56
|
+
# @return [Time] When the photo was uploaded to Strava
|
|
17
57
|
property 'uploaded_at', transform_with: ->(v) { Time.parse(v) }
|
|
58
|
+
|
|
59
|
+
# @return [Time] When the photo was created/taken
|
|
18
60
|
property 'created_at', transform_with: ->(v) { Time.parse(v) }
|
|
61
|
+
|
|
62
|
+
# @return [Time] Local time when photo was created
|
|
19
63
|
property 'created_at_local', transform_with: ->(v) { Time.parse(v) }
|
|
64
|
+
|
|
65
|
+
# @return [Hash] Map of size keys to photo URLs (e.g., {"0" => "https://...", "1000" => "https://..."})
|
|
20
66
|
property 'urls'
|
|
67
|
+
|
|
68
|
+
# @return [String, nil] URL to placeholder/thumbnail image
|
|
21
69
|
property 'placeholder_image'
|
|
70
|
+
|
|
71
|
+
# @return [Hash] Map of size keys to dimensions [width, height]
|
|
22
72
|
property 'sizes'
|
|
73
|
+
|
|
74
|
+
# @return [Boolean] Whether this is the default/cover photo for the activity
|
|
23
75
|
property 'default_photo'
|
|
76
|
+
|
|
77
|
+
# @return [String, nil] Pagination cursor for photo listing
|
|
24
78
|
property 'cursor'
|
|
79
|
+
|
|
80
|
+
# @return [Float, nil] Duration in seconds (for videos)
|
|
25
81
|
property 'duration'
|
|
82
|
+
|
|
83
|
+
# @return [String, nil] Direct URL to video file
|
|
26
84
|
property 'video_url'
|
|
85
|
+
|
|
86
|
+
# @return [Array<Float>, nil] Geographic location [latitude, longitude] where photo was taken
|
|
27
87
|
property 'location'
|
|
28
88
|
end
|
|
29
89
|
end
|
|
@@ -2,10 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents detailed photo information for an activity.
|
|
7
|
+
#
|
|
8
|
+
# Contains the primary photo and total photo count for an activity.
|
|
9
|
+
# This model is not documented in the official Strava API reference.
|
|
10
|
+
#
|
|
11
|
+
# @note This model is not documented by Strava API documentation. Properties
|
|
12
|
+
# are inferred from API responses.
|
|
13
|
+
#
|
|
14
|
+
# @see Strava::Models::DetailedActivity
|
|
15
|
+
# @see Strava::Models::DetailedPhoto
|
|
16
|
+
#
|
|
17
|
+
# @example Accessing activity photos
|
|
18
|
+
# activity = client.activity(1234567890)
|
|
19
|
+
# if activity.photos
|
|
20
|
+
# puts "Total photos: #{activity.photos.count}"
|
|
21
|
+
# if activity.photos.primary
|
|
22
|
+
# puts "Primary photo ID: #{activity.photos.primary.id}"
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
6
26
|
class DetailedPhotos < Strava::Models::Response
|
|
27
|
+
# @return [Photo, nil] The primary/featured photo for the activity
|
|
28
|
+
# @note Not documented by Strava API
|
|
7
29
|
property 'primary', transform_with: ->(v) { Strava::Models::Photo.new(v) }
|
|
30
|
+
|
|
31
|
+
# @return [Boolean, nil] Whether to use the primary photo for display
|
|
32
|
+
# @note Not documented by Strava API
|
|
8
33
|
property 'use_primary_photo'
|
|
34
|
+
|
|
35
|
+
# @return [Integer, nil] Total number of photos attached to the activity
|
|
36
|
+
# @note Not documented by Strava API
|
|
9
37
|
property 'count'
|
|
10
38
|
end
|
|
11
39
|
end
|
|
@@ -2,39 +2,126 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents detailed information about a Strava segment.
|
|
7
|
+
#
|
|
8
|
+
# Segments are specific sections of road or trail where athletes can compete
|
|
9
|
+
# for best times. This model contains comprehensive segment information including
|
|
10
|
+
# location, elevation profile, statistics, and the athlete's personal records.
|
|
11
|
+
#
|
|
12
|
+
# Includes helper mixins for formatting distance and elevation.
|
|
13
|
+
#
|
|
14
|
+
# @example Get segment details
|
|
15
|
+
# segment = client.segment(229781)
|
|
16
|
+
# puts segment.name
|
|
17
|
+
# puts "#{segment.distance_s} with #{segment.average_grade}% average grade"
|
|
18
|
+
# puts "Location: #{segment.city}, #{segment.state}"
|
|
19
|
+
# puts "#{segment.athlete_count} athletes have ridden this segment"
|
|
20
|
+
#
|
|
21
|
+
# if segment.athlete_segment_stats
|
|
22
|
+
# pr = segment.athlete_segment_stats
|
|
23
|
+
# puts "Your PR: #{pr.elapsed_time_in_hours_s}"
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# @see SummarySegment
|
|
27
|
+
# @see https://developers.strava.com/docs/reference/#api-models-DetailedSegment
|
|
28
|
+
#
|
|
6
29
|
class DetailedSegment < Strava::Models::Response
|
|
30
|
+
# @return [Integer] Segment ID
|
|
7
31
|
property 'id'
|
|
32
|
+
|
|
33
|
+
# @return [String] Segment name
|
|
8
34
|
property 'name'
|
|
35
|
+
|
|
36
|
+
# @return [String] Activity type ('Ride' or 'Run')
|
|
9
37
|
property 'activity_type'
|
|
38
|
+
|
|
10
39
|
include Mixins::Distance
|
|
40
|
+
|
|
41
|
+
# @return [Float] Average grade as a percentage
|
|
11
42
|
property 'average_grade'
|
|
43
|
+
|
|
44
|
+
# @return [Float] Maximum grade as a percentage
|
|
12
45
|
property 'maximum_grade'
|
|
46
|
+
|
|
47
|
+
# @return [Float] Highest elevation point in meters
|
|
13
48
|
property 'elevation_high'
|
|
49
|
+
|
|
50
|
+
# @return [Float] Lowest elevation point in meters
|
|
14
51
|
property 'elevation_low'
|
|
52
|
+
|
|
53
|
+
# @return [LatLng] Starting coordinates [latitude, longitude]
|
|
15
54
|
property 'start_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
|
|
55
|
+
|
|
56
|
+
# @return [LatLng] Ending coordinates [latitude, longitude]
|
|
16
57
|
property 'end_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
|
|
58
|
+
|
|
59
|
+
# @return [Integer] Climb category (0 = uncategorized, 1-5 = category climbs, HC = hors catégorie)
|
|
17
60
|
property 'climb_category'
|
|
61
|
+
|
|
62
|
+
# @return [String, nil] City where the segment is located
|
|
18
63
|
property 'city'
|
|
64
|
+
|
|
65
|
+
# @return [String, nil] State/province where the segment is located
|
|
19
66
|
property 'state'
|
|
67
|
+
|
|
68
|
+
# @return [String, nil] Country where the segment is located
|
|
20
69
|
property 'country'
|
|
70
|
+
|
|
71
|
+
# @return [Boolean] Whether this segment is private
|
|
21
72
|
property 'private'
|
|
73
|
+
|
|
74
|
+
# @return [SummaryPRSegmentEffort, nil] The authenticated athlete's PR on this segment
|
|
22
75
|
property 'athlete_pr_effort', transform_with: ->(v) { Strava::Models::SummaryPRSegmentEffort.new(v) }
|
|
76
|
+
|
|
77
|
+
# @return [SummarySegmentEffort, nil] The authenticated athlete's statistics on this segment
|
|
23
78
|
property 'athlete_segment_stats', transform_with: ->(v) { Strava::Models::SummarySegmentEffort.new(v) }
|
|
79
|
+
|
|
80
|
+
# @return [Time] When the segment was created
|
|
24
81
|
property 'created_at', transform_with: ->(v) { Time.parse(v) }
|
|
82
|
+
|
|
83
|
+
# @return [Time] When the segment was last updated
|
|
25
84
|
property 'updated_at', transform_with: ->(v) { Time.parse(v) }
|
|
85
|
+
|
|
26
86
|
include Mixins::TotalElevationGain
|
|
87
|
+
|
|
88
|
+
# @return [Map] Segment map with polyline data
|
|
27
89
|
property 'map', transform_with: ->(v) { Strava::Models::Map.new(v) }
|
|
90
|
+
|
|
91
|
+
# @return [Integer] Total number of efforts on this segment
|
|
28
92
|
property 'effort_count'
|
|
93
|
+
|
|
94
|
+
# @return [Integer] Total number of unique athletes who have attempted this segment
|
|
29
95
|
property 'athlete_count'
|
|
96
|
+
|
|
97
|
+
# @return [Boolean] Whether this segment has been flagged as hazardous
|
|
30
98
|
property 'hazardous'
|
|
99
|
+
|
|
100
|
+
# @return [Integer] Number of athletes who have starred this segment
|
|
31
101
|
property 'star_count'
|
|
32
|
-
|
|
102
|
+
|
|
103
|
+
# @note Undocumented in official API
|
|
104
|
+
# @return [Integer, nil] Resource state indicator
|
|
33
105
|
property 'resource_state'
|
|
106
|
+
|
|
107
|
+
# @note Undocumented in official API
|
|
108
|
+
# @return [String, nil] Elevation profile data (deprecated, use elevation_profiles)
|
|
34
109
|
property 'elevation_profile'
|
|
110
|
+
|
|
111
|
+
# @note Undocumented in official API
|
|
112
|
+
# @return [Array, nil] Collection of elevation profile data points
|
|
35
113
|
property 'elevation_profiles'
|
|
114
|
+
|
|
115
|
+
# @note Undocumented in official API
|
|
116
|
+
# @return [Boolean, nil] Whether the authenticated athlete has starred this segment
|
|
36
117
|
property 'starred'
|
|
118
|
+
|
|
119
|
+
# @note Undocumented in official API
|
|
120
|
+
# @return [Xoms, nil] QOM/KOM information for this segment
|
|
37
121
|
property 'xoms', transform_with: ->(v) { Strava::Models::Xoms.new(v) }
|
|
122
|
+
|
|
123
|
+
# @note Undocumented in official API
|
|
124
|
+
# @return [LocalLegend, nil] Current Local Legend holder for this segment
|
|
38
125
|
property 'local_legend', transform_with: ->(v) { Strava::Models::LocalLegend.new(v) }
|
|
39
126
|
end
|
|
40
127
|
end
|
|
@@ -2,35 +2,124 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents detailed information about a segment effort within an activity.
|
|
7
|
+
#
|
|
8
|
+
# A segment effort is an attempt at a defined segment (a portion of road or trail).
|
|
9
|
+
# The detailed version includes comprehensive statistics, rankings, achievements,
|
|
10
|
+
# and sensor data for the effort.
|
|
11
|
+
#
|
|
12
|
+
# @see https://developers.strava.com/docs/reference/#api-models-DetailedSegmentEffort Strava API DetailedSegmentEffort reference
|
|
13
|
+
# @see Strava::Models::SummarySegmentEffort
|
|
14
|
+
# @see Strava::Models::SummarySegment
|
|
15
|
+
# @see Strava::Models::Achievement
|
|
16
|
+
#
|
|
17
|
+
# @example Accessing detailed segment effort
|
|
18
|
+
# effort = client.segment_effort(1234567890)
|
|
19
|
+
#
|
|
20
|
+
# puts "Segment: #{effort.name}"
|
|
21
|
+
# puts "Time: #{effort.elapsed_time_in_hours_s}"
|
|
22
|
+
# puts "Moving time: #{effort.moving_time_in_hours_s}"
|
|
23
|
+
# puts "Distance: #{effort.distance_s}"
|
|
24
|
+
#
|
|
25
|
+
# if effort.average_watts
|
|
26
|
+
# puts "Avg Power: #{effort.average_watts}W"
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# if effort.average_heartrate
|
|
30
|
+
# puts "Avg HR: #{effort.average_heartrate} bpm (max: #{effort.max_heartrate})"
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
# # Check rankings
|
|
34
|
+
# puts "KOM Rank: #{effort.kom_rank}" if effort.kom_rank
|
|
35
|
+
# puts "PR Rank: #{effort.pr_rank}" if effort.pr_rank
|
|
36
|
+
#
|
|
37
|
+
# # View achievements
|
|
38
|
+
# effort.achievements.each do |achievement|
|
|
39
|
+
# puts "Achievement: #{achievement.type} - Rank #{achievement.rank}"
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
6
42
|
class DetailedSegmentEffort < Strava::Models::Response
|
|
43
|
+
# @return [Integer] Unique identifier for this segment effort
|
|
7
44
|
property 'id'
|
|
45
|
+
|
|
46
|
+
# @return [Integer] ID of the activity containing this segment effort
|
|
8
47
|
property 'activity_id'
|
|
48
|
+
|
|
49
|
+
# Includes elapsed_time (total time including stops) and helper methods
|
|
9
50
|
include Mixins::ElapsedTime
|
|
51
|
+
|
|
52
|
+
# @return [Time] Start time of the segment effort in UTC
|
|
10
53
|
property 'start_date', transform_with: ->(v) { Time.parse(v) }
|
|
54
|
+
|
|
55
|
+
# Includes start_date_local with timezone handling
|
|
11
56
|
include Mixins::StartDateLocal
|
|
57
|
+
|
|
58
|
+
# Includes distance in meters and conversion helper methods
|
|
12
59
|
include Mixins::Distance
|
|
60
|
+
|
|
61
|
+
# @return [Boolean] Whether this effort achieved KOM (King/Queen of the Mountain)
|
|
13
62
|
property 'is_kom'
|
|
63
|
+
|
|
64
|
+
# @return [String] Name of the segment
|
|
14
65
|
property 'name'
|
|
15
|
-
|
|
66
|
+
|
|
67
|
+
# @return [MetaActivity] Reference to the parent activity
|
|
16
68
|
property 'activity', transform_with: ->(v) { Strava::Models::MetaActivity.new(v) }
|
|
69
|
+
|
|
70
|
+
# @return [MetaAthlete] Reference to the athlete who performed this effort
|
|
17
71
|
property 'athlete', transform_with: ->(v) { Strava::Models::MetaAthlete.new(v) }
|
|
72
|
+
|
|
73
|
+
# Includes moving_time (time excluding stops) and helper methods
|
|
18
74
|
include Mixins::MovingTime
|
|
75
|
+
|
|
76
|
+
# @return [Integer] Index in the activity stream where this effort starts
|
|
19
77
|
property 'start_index'
|
|
78
|
+
|
|
79
|
+
# @return [Integer] Index in the activity stream where this effort ends
|
|
20
80
|
property 'end_index'
|
|
81
|
+
|
|
82
|
+
# @return [Float, nil] Average cadence during the effort (RPM for cycling, steps/min for running)
|
|
21
83
|
property 'average_cadence'
|
|
84
|
+
|
|
85
|
+
# @return [Float, nil] Average power output during the effort in watts
|
|
22
86
|
property 'average_watts'
|
|
87
|
+
|
|
88
|
+
# @return [Boolean, nil] Whether power data comes from a power meter device
|
|
23
89
|
property 'device_watts'
|
|
90
|
+
|
|
91
|
+
# @return [Float, nil] Average heart rate during the effort in beats per minute
|
|
24
92
|
property 'average_heartrate'
|
|
93
|
+
|
|
94
|
+
# @return [Integer, nil] Maximum heart rate during the effort in beats per minute
|
|
25
95
|
property 'max_heartrate'
|
|
96
|
+
|
|
97
|
+
# @return [SummarySegment] The segment that was attempted
|
|
26
98
|
property 'segment', transform_with: ->(v) { Strava::Models::SummarySegment.new(v) }
|
|
99
|
+
|
|
100
|
+
# @return [Integer, nil] Overall rank on this segment (null if not in top 10)
|
|
27
101
|
property 'kom_rank'
|
|
102
|
+
|
|
103
|
+
# @return [Integer, nil] Personal record rank for this segment (1 for PR, 2 for 2nd best, etc.)
|
|
28
104
|
property 'pr_rank'
|
|
105
|
+
|
|
106
|
+
# @return [Boolean] Whether this effort is hidden from public segment leaderboards
|
|
29
107
|
property 'hidden'
|
|
30
|
-
|
|
108
|
+
|
|
109
|
+
# @return [Integer] Resource state indicator
|
|
110
|
+
# @note Not documented by Strava API
|
|
31
111
|
property 'resource_state'
|
|
112
|
+
|
|
113
|
+
# @return [Array<Achievement>] Achievements earned during this effort (PR, yearly records, etc.)
|
|
114
|
+
# @note Not documented by Strava API
|
|
32
115
|
property 'achievements', transform_with: ->(v) { v.map { |r| Strava::Models::Achievement.new(r) } }
|
|
116
|
+
|
|
117
|
+
# @return [String, nil] Visibility setting for this effort
|
|
118
|
+
# @note Not documented by Strava API
|
|
33
119
|
property 'visibility'
|
|
120
|
+
|
|
121
|
+
# @return [SummaryPRSegmentEffort, nil] Athlete's personal statistics for this segment
|
|
122
|
+
# @note Not documented by Strava API
|
|
34
123
|
property 'athlete_segment_stats', transform_with: ->(v) { Strava::Models::SummaryPRSegmentEffort.new(v) }
|
|
35
124
|
end
|
|
36
125
|
end
|
|
@@ -2,22 +2,75 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents a segment found via segment exploration.
|
|
7
|
+
#
|
|
8
|
+
# Used when searching for segments in a geographic area. Contains basic segment
|
|
9
|
+
# information including location, elevation, and difficulty category.
|
|
10
|
+
#
|
|
11
|
+
# @see https://developers.strava.com/docs/reference/#api-models-ExplorerSegment Strava API ExplorerSegment reference
|
|
12
|
+
# @see Strava::Api::Client#explore_segments
|
|
13
|
+
# @see Strava::Models::SummarySegment
|
|
14
|
+
#
|
|
15
|
+
# @example Exploring segments near a location
|
|
16
|
+
# segments = client.explore_segments(
|
|
17
|
+
# bounds: [37.7, -122.5, 37.8, -122.4], # [sw_lat, sw_lng, ne_lat, ne_lng]
|
|
18
|
+
# activity_type: 'running'
|
|
19
|
+
# )
|
|
20
|
+
#
|
|
21
|
+
# segments.each do |segment|
|
|
22
|
+
# puts "#{segment.name} (#{segment.distance_s})"
|
|
23
|
+
# puts " Climb: #{segment.climb_category_desc}"
|
|
24
|
+
# puts " Grade: #{segment.avg_grade}%"
|
|
25
|
+
# puts " Elevation: #{segment.elev_difference}m"
|
|
26
|
+
# puts " Starred: #{segment.starred}"
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
6
29
|
class ExplorerSegment < Strava::Models::Response
|
|
30
|
+
# @return [Integer] Unique identifier for this segment
|
|
7
31
|
property 'id'
|
|
32
|
+
|
|
33
|
+
# @return [String] Name of the segment
|
|
8
34
|
property 'name'
|
|
35
|
+
|
|
36
|
+
# @return [Integer] Climb category (0=uncategorized, 5=easiest, 1=hardest, HC=hors catégorie)
|
|
9
37
|
property 'climb_category'
|
|
38
|
+
|
|
39
|
+
# @return [String] Human-readable description of climb category (e.g., "NC", "4", "3", "2", "1", "HC")
|
|
10
40
|
property 'climb_category_desc'
|
|
41
|
+
|
|
42
|
+
# @return [Float] Average grade/incline as a percentage
|
|
11
43
|
property 'avg_grade'
|
|
44
|
+
|
|
45
|
+
# @return [LatLng] GPS coordinates of segment start point
|
|
12
46
|
property 'start_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
|
|
47
|
+
|
|
48
|
+
# @return [LatLng] GPS coordinates of segment end point
|
|
13
49
|
property 'end_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
|
|
50
|
+
|
|
51
|
+
# @return [Float] Net elevation difference in meters (positive for climbs, negative for descents)
|
|
14
52
|
property 'elev_difference'
|
|
53
|
+
|
|
54
|
+
# Includes distance in meters and conversion helper methods
|
|
15
55
|
include Mixins::Distance
|
|
56
|
+
|
|
57
|
+
# @return [String, nil] Encoded polyline of the segment path
|
|
16
58
|
property 'points'
|
|
17
|
-
|
|
59
|
+
|
|
60
|
+
# @return [Integer] Resource state indicator
|
|
61
|
+
# @note Not documented by Strava API
|
|
18
62
|
property 'resource_state'
|
|
63
|
+
|
|
64
|
+
# @return [Boolean, nil] Whether the current athlete has starred this segment
|
|
65
|
+
# @note Not documented by Strava API
|
|
19
66
|
property 'starred'
|
|
67
|
+
|
|
68
|
+
# @return [String, nil] URL or path to elevation profile visualization
|
|
69
|
+
# @note Not documented by Strava API
|
|
20
70
|
property 'elevation_profile'
|
|
71
|
+
|
|
72
|
+
# @return [Boolean, nil] Whether local legend feature is enabled for this segment
|
|
73
|
+
# @note Not documented by Strava API
|
|
21
74
|
property 'local_legend_enabled'
|
|
22
75
|
end
|
|
23
76
|
end
|
|
@@ -2,9 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents an athlete's heart rate zone configuration.
|
|
7
|
+
#
|
|
8
|
+
# Heart rate zones define intensity levels based on beats per minute.
|
|
9
|
+
# Athletes can use default zones or configure custom zones based on
|
|
10
|
+
# their fitness level and training goals.
|
|
11
|
+
#
|
|
12
|
+
# @see https://developers.strava.com/docs/reference/#api-models-HeartRateZoneRanges Strava API HeartRateZoneRanges reference
|
|
13
|
+
# @see Strava::Models::ZoneRange
|
|
14
|
+
# @see Strava::Models::Zones
|
|
15
|
+
#
|
|
16
|
+
# @example Accessing heart rate zones
|
|
17
|
+
# zones = client.athlete_zones
|
|
18
|
+
#
|
|
19
|
+
# if zones.heart_rate
|
|
20
|
+
# if zones.heart_rate.custom_zones
|
|
21
|
+
# puts "Using custom heart rate zones"
|
|
22
|
+
# else
|
|
23
|
+
# puts "Using default heart rate zones"
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# zones.heart_rate.zones.each_with_index do |zone, i|
|
|
27
|
+
# puts "Zone #{i + 1}: #{zone.min}-#{zone.max} bpm"
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
6
31
|
class HeartRateZoneRanges < Strava::Models::Response
|
|
32
|
+
# @return [Boolean] Whether the athlete is using custom heart rate zones
|
|
7
33
|
property 'custom_zones'
|
|
34
|
+
|
|
35
|
+
# @return [Array<ZoneRange>] Array of heart rate zone ranges
|
|
8
36
|
property 'zones', transform_with: ->(v) { v.map { |r| Strava::Models::ZoneRange.new(r) } }
|
|
9
37
|
end
|
|
10
38
|
end
|
|
@@ -2,11 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents a user who gave kudos to an activity.
|
|
7
|
+
#
|
|
8
|
+
# Kudos are a way for athletes to show appreciation for each other's activities.
|
|
9
|
+
# This model is not documented in the official Strava API reference.
|
|
10
|
+
#
|
|
11
|
+
# @note This model is not documented by Strava API documentation. Properties
|
|
12
|
+
# are inferred from API responses.
|
|
13
|
+
#
|
|
14
|
+
# @see Strava::Api::Client#activity_kudos
|
|
15
|
+
#
|
|
16
|
+
# @example Listing kudos for an activity
|
|
17
|
+
# kudos = client.activity_kudos(1234567890)
|
|
18
|
+
# kudos.each do |kudoser|
|
|
19
|
+
# puts "#{kudoser.display_name} gave kudos"
|
|
20
|
+
# puts " Avatar: #{kudoser.avatar_url}"
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
6
23
|
class Kudoser < Strava::Models::Response
|
|
24
|
+
# @return [String, nil] URL to the athlete's profile page
|
|
25
|
+
# @note Not documented by Strava API
|
|
7
26
|
property 'destination_url'
|
|
27
|
+
|
|
28
|
+
# @return [String, nil] Display name of the athlete who gave kudos
|
|
29
|
+
# @note Not documented by Strava API
|
|
8
30
|
property 'display_name'
|
|
31
|
+
|
|
32
|
+
# @return [String, nil] URL to the athlete's avatar image
|
|
33
|
+
# @note Not documented by Strava API
|
|
9
34
|
property 'avatar_url'
|
|
35
|
+
|
|
36
|
+
# @return [Boolean, nil] Whether to show the athlete's name
|
|
37
|
+
# @note Not documented by Strava API
|
|
10
38
|
property 'show_name'
|
|
11
39
|
end
|
|
12
40
|
end
|
data/lib/strava/models/lap.rb
CHANGED
|
@@ -2,31 +2,91 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents a lap within an activity.
|
|
7
|
+
#
|
|
8
|
+
# Laps are splits within an activity, either created manually by the athlete
|
|
9
|
+
# or auto-generated by the recording device. Each lap contains metrics like
|
|
10
|
+
# distance, time, speed, and elevation for that specific segment of the activity.
|
|
11
|
+
#
|
|
12
|
+
# Includes helper mixins for formatting distance, time, and elevation.
|
|
13
|
+
#
|
|
14
|
+
# @example List activity laps
|
|
15
|
+
# laps = client.activity_laps(1234567890)
|
|
16
|
+
# laps.each_with_index do |lap, i|
|
|
17
|
+
# puts "Lap #{i+1}: #{lap.name}"
|
|
18
|
+
# puts "Distance: #{lap.distance_s}"
|
|
19
|
+
# puts "Time: #{lap.moving_time_in_hours_s}"
|
|
20
|
+
# puts "Elevation: #{lap.total_elevation_gain_s}"
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# @see https://developers.strava.com/docs/reference/#api-models-Lap
|
|
24
|
+
#
|
|
6
25
|
class Lap < Strava::Models::Response
|
|
26
|
+
# @return [Integer] Lap ID
|
|
7
27
|
property 'id'
|
|
28
|
+
|
|
29
|
+
# @return [MetaActivity] The activity this lap belongs to
|
|
8
30
|
property 'activity', transform_with: ->(v) { Strava::Models::MetaActivity.new(v) }
|
|
31
|
+
|
|
32
|
+
# @return [MetaAthlete] The athlete who recorded this lap
|
|
9
33
|
property 'athlete', transform_with: ->(v) { Strava::Models::MetaAthlete.new(v) }
|
|
34
|
+
|
|
35
|
+
# @return [Float, nil] Average cadence (RPM for cycling, steps/minute for running)
|
|
10
36
|
property 'average_cadence'
|
|
37
|
+
|
|
38
|
+
# @return [Float] Average speed in meters per second
|
|
11
39
|
property 'average_speed'
|
|
40
|
+
|
|
12
41
|
include Mixins::Distance
|
|
13
42
|
include Mixins::MovingTime
|
|
14
43
|
include Mixins::ElapsedTime
|
|
44
|
+
|
|
45
|
+
# @return [Integer] Starting index in the activity's data stream
|
|
15
46
|
property 'start_index'
|
|
47
|
+
|
|
48
|
+
# @return [Integer] Ending index in the activity's data stream
|
|
16
49
|
property 'end_index'
|
|
50
|
+
|
|
51
|
+
# @return [Integer] The lap number (1-indexed)
|
|
17
52
|
property 'lap_index'
|
|
53
|
+
|
|
54
|
+
# @return [Float] Maximum speed in meters per second
|
|
18
55
|
property 'max_speed'
|
|
56
|
+
|
|
57
|
+
# @return [String] Lap name (e.g., 'Lap 1', 'Manual Lap')
|
|
19
58
|
property 'name'
|
|
59
|
+
|
|
60
|
+
# @return [Integer, nil] Pace zone indicator
|
|
20
61
|
property 'pace_zone'
|
|
62
|
+
|
|
63
|
+
# @return [Integer, nil] Split number within the lap
|
|
21
64
|
property 'split'
|
|
65
|
+
|
|
66
|
+
# @return [Time] Start date and time (UTC)
|
|
22
67
|
property 'start_date', transform_with: ->(v) { Time.parse(v) }
|
|
68
|
+
|
|
23
69
|
include Mixins::StartDateLocal
|
|
24
70
|
include Mixins::TotalElevationGain
|
|
25
|
-
|
|
71
|
+
|
|
72
|
+
# @note Undocumented in official API
|
|
73
|
+
# @return [Integer, nil] Resource state indicator
|
|
26
74
|
property 'resource_state'
|
|
75
|
+
|
|
76
|
+
# @note Undocumented in official API
|
|
77
|
+
# @return [Boolean, nil] Whether the watts are from a power meter (true) or estimated (false)
|
|
27
78
|
property 'device_watts'
|
|
79
|
+
|
|
80
|
+
# @note Undocumented in official API
|
|
81
|
+
# @return [Float, nil] Average power in watts
|
|
28
82
|
property 'average_watts'
|
|
83
|
+
|
|
84
|
+
# @note Undocumented in official API
|
|
85
|
+
# @return [Float, nil] Average heart rate in beats per minute
|
|
29
86
|
property 'average_heartrate'
|
|
87
|
+
|
|
88
|
+
# @note Undocumented in official API
|
|
89
|
+
# @return [Float, nil] Maximum heart rate in beats per minute
|
|
30
90
|
property 'max_heartrate'
|
|
31
91
|
end
|
|
32
92
|
end
|