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,19 +2,75 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents statistics about similar activities.
|
|
7
|
+
#
|
|
8
|
+
# Provides comparative data about activities of the same type and route,
|
|
9
|
+
# including speed trends and performance metrics. This model is not documented
|
|
10
|
+
# in the official Strava API reference.
|
|
11
|
+
#
|
|
12
|
+
# @note This model is not documented by Strava API documentation. Properties
|
|
13
|
+
# are inferred from API responses.
|
|
14
|
+
#
|
|
15
|
+
# @see Strava::Models::Trend
|
|
16
|
+
# @see Strava::Models::DetailedActivity
|
|
17
|
+
#
|
|
18
|
+
# @example Accessing similar activity statistics
|
|
19
|
+
# activity = client.activity(1234567890)
|
|
20
|
+
# if activity.similar_activities
|
|
21
|
+
# similar = activity.similar_activities
|
|
22
|
+
# puts "Average speed: #{similar.average_speed} m/s"
|
|
23
|
+
# puts "Similar efforts: #{similar.effort_count}"
|
|
24
|
+
# puts "PR rank: #{similar.pr_rank}"
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
6
27
|
class SimilarActivities < Strava::Models::Response
|
|
28
|
+
# @return [Float, nil] Average speed across similar activities in meters per second
|
|
29
|
+
# @note Not documented by Strava API
|
|
7
30
|
property 'average_speed'
|
|
31
|
+
|
|
32
|
+
# @return [Integer, nil] Resource state indicator
|
|
33
|
+
# @note Not documented by Strava API
|
|
8
34
|
property 'resource_state'
|
|
35
|
+
|
|
36
|
+
# @return [Integer, nil] Number of similar efforts/activities
|
|
37
|
+
# @note Not documented by Strava API
|
|
9
38
|
property 'effort_count'
|
|
39
|
+
|
|
40
|
+
# @return [Integer, nil] Milestone frequency indicator
|
|
41
|
+
# @note Not documented by Strava API
|
|
10
42
|
property 'frequency_milestone'
|
|
43
|
+
|
|
44
|
+
# @return [Float, nil] Maximum average speed across similar activities in meters per second
|
|
45
|
+
# @note Not documented by Strava API
|
|
11
46
|
property 'max_average_speed'
|
|
47
|
+
|
|
48
|
+
# @return [Float, nil] Median average speed across similar activities in meters per second
|
|
49
|
+
# @note Not documented by Strava API
|
|
12
50
|
property 'mid_average_speed'
|
|
51
|
+
|
|
52
|
+
# @return [Float, nil] Minimum average speed across similar activities in meters per second
|
|
53
|
+
# @note Not documented by Strava API
|
|
13
54
|
property 'min_average_speed'
|
|
55
|
+
|
|
56
|
+
# @return [Float, nil] Median speed value
|
|
57
|
+
# @note Not documented by Strava API
|
|
14
58
|
property 'mid_speed'
|
|
59
|
+
|
|
60
|
+
# @return [Float, nil] Minimum speed value
|
|
61
|
+
# @note Not documented by Strava API
|
|
15
62
|
property 'min_speed'
|
|
63
|
+
|
|
64
|
+
# @return [Array, nil] Array of speed values
|
|
65
|
+
# @note Not documented by Strava API
|
|
16
66
|
property 'speeds'
|
|
67
|
+
|
|
68
|
+
# @return [Trend, nil] Trend data for similar activities
|
|
69
|
+
# @note Not documented by Strava API
|
|
17
70
|
property 'trend', transform_with: ->(v) { Strava::Models::Trend.new(v) }
|
|
71
|
+
|
|
72
|
+
# @return [Integer, nil] Personal record rank among similar activities
|
|
73
|
+
# @note Not documented by Strava API
|
|
18
74
|
property 'pr_rank'
|
|
19
75
|
end
|
|
20
76
|
end
|
data/lib/strava/models/split.rb
CHANGED
|
@@ -2,17 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents a split/interval within an activity.
|
|
7
|
+
#
|
|
8
|
+
# Splits divide an activity into equal distance segments (e.g., per mile or per kilometer)
|
|
9
|
+
# with metrics for each segment. Activities typically include both metric (km) and
|
|
10
|
+
# standard (mile) splits.
|
|
11
|
+
#
|
|
12
|
+
# Includes helper mixins for formatting distance, time, speed, and elevation.
|
|
13
|
+
#
|
|
14
|
+
# @example Access activity splits
|
|
15
|
+
# activity = client.activity(1234567890)
|
|
16
|
+
# activity.splits_metric.each_with_index do |split, i|
|
|
17
|
+
# puts "KM #{i+1}: #{split.moving_time_in_hours_s} at #{split.pace_s}"
|
|
18
|
+
# puts "Elevation: #{split.elevation_difference}m"
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# @see https://developers.strava.com/docs/reference/#api-models-Split
|
|
22
|
+
#
|
|
6
23
|
class Split < Strava::Models::Response
|
|
7
24
|
include Mixins::AverageSpeed
|
|
8
25
|
include Mixins::Distance
|
|
9
26
|
include Mixins::ElapsedTime
|
|
10
27
|
include Mixins::ElevationDifference
|
|
28
|
+
|
|
29
|
+
# @return [Integer] Pace zone for this split (0-5)
|
|
11
30
|
property 'pace_zone'
|
|
31
|
+
|
|
12
32
|
include Mixins::MovingTime
|
|
33
|
+
|
|
34
|
+
# @return [Integer] Split number (1-indexed)
|
|
13
35
|
property 'split'
|
|
14
|
-
|
|
36
|
+
|
|
37
|
+
# @return [Float] Average speed adjusted for grade/incline (in meters per second)
|
|
15
38
|
property 'average_grade_adjusted_speed'
|
|
39
|
+
|
|
40
|
+
# @return [Float] Average heart rate during this split (beats per minute)
|
|
16
41
|
property 'average_heartrate'
|
|
17
42
|
end
|
|
18
43
|
end
|
|
@@ -2,9 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents visibility settings for activity statistics.
|
|
7
|
+
#
|
|
8
|
+
# Controls which statistics are visible to others when viewing 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
|
+
#
|
|
16
|
+
# @example Accessing stats visibility
|
|
17
|
+
# activity = client.activity(1234567890)
|
|
18
|
+
# if activity.stats_visibility
|
|
19
|
+
# activity.stats_visibility.each do |visibility|
|
|
20
|
+
# puts "#{visibility.type}: #{visibility.visibility}"
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
6
24
|
class StatsVisibility < Strava::Models::Response
|
|
25
|
+
# @return [String, nil] Type of statistic (e.g., "heartrate", "power")
|
|
26
|
+
# @note Not documented by Strava API
|
|
7
27
|
property 'type'
|
|
28
|
+
|
|
29
|
+
# @return [String, nil] Visibility setting (e.g., "everyone", "followers_only", "only_me")
|
|
30
|
+
# @note Not documented by Strava API
|
|
8
31
|
property 'visibility'
|
|
9
32
|
end
|
|
10
33
|
end
|
data/lib/strava/models/stream.rb
CHANGED
|
@@ -2,11 +2,118 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
+
#
|
|
6
|
+
# Represents a single stream of time-series data from the Strava API.
|
|
7
|
+
#
|
|
8
|
+
# A Stream contains both metadata about the data collection and the actual data array.
|
|
9
|
+
# Common stream types include: time, distance, latlng, altitude, velocity_smooth,
|
|
10
|
+
# heartrate, cadence, watts, temp, moving, and grade_smooth.
|
|
11
|
+
#
|
|
12
|
+
# @see https://developers.strava.com/docs/reference/#api-Streams Strava API Streams reference
|
|
13
|
+
# @see Strava::Models::BaseStream
|
|
14
|
+
# @see Strava::Models::StreamSet
|
|
15
|
+
#
|
|
16
|
+
# @example Accessing heartrate stream data
|
|
17
|
+
# streams = client.activity_streams(1234567890, keys: 'heartrate,watts')
|
|
18
|
+
# hr_data = streams.heartrate.data
|
|
19
|
+
# puts "Average HR: #{hr_data.sum / hr_data.size}"
|
|
20
|
+
# puts "Max HR: #{hr_data.max}"
|
|
21
|
+
#
|
|
22
|
+
# @example Working with GPS coordinates
|
|
23
|
+
# streams = client.activity_streams(1234567890, keys: 'latlng')
|
|
24
|
+
# coords = streams.latlng.data # Array of [lat, lng] pairs
|
|
25
|
+
# coords.each do |lat, lng|
|
|
26
|
+
# puts "#{lat}, #{lng}"
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# @example Computing elevation gain and loss from an altitude stream
|
|
30
|
+
# streams = client.activity_streams(1234567890, keys: 'altitude')
|
|
31
|
+
# puts streams.altitude.total_elevation_gain_s # => "725.3m"
|
|
32
|
+
# puts streams.altitude.total_elevation_loss_s # => "680.1m"
|
|
33
|
+
#
|
|
5
34
|
class Stream < Strava::Models::Response
|
|
35
|
+
# @return [Integer] Total number of data points in the original stream before any resampling
|
|
6
36
|
property 'original_size'
|
|
37
|
+
|
|
38
|
+
# @return [String] Resolution of the stream data ("low", "medium", or "high")
|
|
7
39
|
property 'resolution'
|
|
40
|
+
|
|
41
|
+
# @return [String] Type of series - how data points are indexed ("time" or "distance")
|
|
8
42
|
property 'series_type'
|
|
43
|
+
|
|
44
|
+
# @return [Array] Array of data points. The type of data depends on the stream:
|
|
45
|
+
# - time: Array of integers (seconds from start)
|
|
46
|
+
# - distance: Array of floats (meters from start)
|
|
47
|
+
# - latlng: Array of [latitude, longitude] coordinate pairs
|
|
48
|
+
# - altitude: Array of floats (meters)
|
|
49
|
+
# - velocity_smooth: Array of floats (meters per second)
|
|
50
|
+
# - heartrate: Array of integers (beats per minute)
|
|
51
|
+
# - cadence: Array of integers (RPM for cycling, steps/min for running)
|
|
52
|
+
# - watts: Array of integers (power in watts)
|
|
53
|
+
# - temp: Array of integers (temperature in celsius)
|
|
54
|
+
# - moving: Array of booleans (true if moving, false if stopped)
|
|
55
|
+
# - grade_smooth: Array of floats (grade as percentage)
|
|
9
56
|
property 'data'
|
|
57
|
+
|
|
58
|
+
#
|
|
59
|
+
# Returns the total elevation gain, calculated as the sum of all positive
|
|
60
|
+
# elevation increases between consecutive data points.
|
|
61
|
+
#
|
|
62
|
+
# This is only meaningful when the stream represents altitude data.
|
|
63
|
+
#
|
|
64
|
+
# @return [Float, nil] Total elevation gain in meters, or nil if data is not present
|
|
65
|
+
#
|
|
66
|
+
# @example
|
|
67
|
+
# streams = client.activity_streams(1234567890, keys: 'altitude')
|
|
68
|
+
# puts streams.altitude.total_elevation_gain # => 725.3
|
|
69
|
+
#
|
|
70
|
+
def total_elevation_gain
|
|
71
|
+
return if data.nil?
|
|
72
|
+
|
|
73
|
+
data.each_cons(2).sum { |a, b| b > a ? b - a : 0 }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#
|
|
77
|
+
# Returns the total elevation loss, calculated as the sum of all negative
|
|
78
|
+
# elevation decreases between consecutive data points.
|
|
79
|
+
#
|
|
80
|
+
# This is only meaningful when the stream represents altitude data.
|
|
81
|
+
#
|
|
82
|
+
# @return [Float, nil] Total elevation loss in meters, or nil if data is not present
|
|
83
|
+
#
|
|
84
|
+
# @example
|
|
85
|
+
# streams = client.activity_streams(1234567890, keys: 'altitude')
|
|
86
|
+
# puts streams.altitude.total_elevation_loss # => 680.1
|
|
87
|
+
#
|
|
88
|
+
def total_elevation_loss
|
|
89
|
+
return if data.nil?
|
|
90
|
+
|
|
91
|
+
data.each_cons(2).sum { |a, b| a > b ? a - b : 0 }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
#
|
|
95
|
+
# Returns formatted total elevation gain in meters.
|
|
96
|
+
#
|
|
97
|
+
# @return [String, nil] Formatted elevation (e.g., "725.3m")
|
|
98
|
+
#
|
|
99
|
+
def total_elevation_gain_s
|
|
100
|
+
gain = total_elevation_gain
|
|
101
|
+
return if gain.nil?
|
|
102
|
+
|
|
103
|
+
format('%gm', format('%.1f', gain))
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
#
|
|
107
|
+
# Returns formatted total elevation loss in meters.
|
|
108
|
+
#
|
|
109
|
+
# @return [String, nil] Formatted elevation (e.g., "680.1m")
|
|
110
|
+
#
|
|
111
|
+
def total_elevation_loss_s
|
|
112
|
+
loss = total_elevation_loss
|
|
113
|
+
return if loss.nil?
|
|
114
|
+
|
|
115
|
+
format('%gm', format('%.1f', loss))
|
|
116
|
+
end
|
|
10
117
|
end
|
|
11
118
|
end
|
|
12
119
|
end
|
|
@@ -2,18 +2,69 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents a collection of activity streams from the Strava API.
|
|
7
|
+
#
|
|
8
|
+
# A StreamSet is returned when requesting activity or segment effort streams
|
|
9
|
+
# and contains multiple synchronized time-series data streams. Each stream
|
|
10
|
+
# contains data points that correspond to the same moments in time or distance.
|
|
11
|
+
#
|
|
12
|
+
# @see https://developers.strava.com/docs/reference/#api-models-StreamSet Strava API StreamSet reference
|
|
13
|
+
# @see Strava::Models::Stream
|
|
14
|
+
# @see Strava::Api::Client#activity_streams
|
|
15
|
+
# @see Strava::Api::Client#segment_effort_streams
|
|
16
|
+
#
|
|
17
|
+
# @example Fetching and analyzing multiple streams
|
|
18
|
+
# streams = client.activity_streams(1234567890,
|
|
19
|
+
# keys: 'time,distance,heartrate,watts',
|
|
20
|
+
# key_by_type: true
|
|
21
|
+
# )
|
|
22
|
+
#
|
|
23
|
+
# # Access individual streams
|
|
24
|
+
# time_data = streams.time.data # Array of elapsed seconds
|
|
25
|
+
# hr_data = streams.heartrate.data # Array of heart rate values
|
|
26
|
+
# power_data = streams.watts.data # Array of power values
|
|
27
|
+
#
|
|
28
|
+
# # Calculate average power for time above threshold HR
|
|
29
|
+
# threshold_hr = 160
|
|
30
|
+
# time_data.each_with_index do |time, i|
|
|
31
|
+
# if hr_data[i] > threshold_hr
|
|
32
|
+
# puts "At #{time}s: HR=#{hr_data[i]}, Power=#{power_data[i]}W"
|
|
33
|
+
# end
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
6
36
|
class StreamSet < Strava::Models::Response
|
|
37
|
+
# @return [Stream, nil] Time stream - elapsed seconds from activity start
|
|
7
38
|
property 'time', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
39
|
+
|
|
40
|
+
# @return [Stream, nil] Distance stream - meters from activity start
|
|
8
41
|
property 'distance', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
42
|
+
|
|
43
|
+
# @return [Stream, nil] GPS coordinate stream - array of [latitude, longitude] pairs
|
|
9
44
|
property 'latlng', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
45
|
+
|
|
46
|
+
# @return [Stream, nil] Altitude stream - elevation in meters
|
|
10
47
|
property 'altitude', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
48
|
+
|
|
49
|
+
# @return [Stream, nil] Smoothed velocity stream - speed in meters per second
|
|
11
50
|
property 'velocity_smooth', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
51
|
+
|
|
52
|
+
# @return [Stream, nil] Heart rate stream - beats per minute
|
|
12
53
|
property 'heartrate', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
54
|
+
|
|
55
|
+
# @return [Stream, nil] Cadence stream - RPM for cycling, steps per minute for running
|
|
13
56
|
property 'cadence', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
57
|
+
|
|
58
|
+
# @return [Stream, nil] Power stream - watts
|
|
14
59
|
property 'watts', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
60
|
+
|
|
61
|
+
# @return [Stream, nil] Temperature stream - degrees celsius
|
|
15
62
|
property 'temp', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
63
|
+
|
|
64
|
+
# @return [Stream, nil] Moving stream - boolean indicating whether athlete is moving
|
|
16
65
|
property 'moving', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
66
|
+
|
|
67
|
+
# @return [Stream, nil] Smoothed grade stream - grade as percentage
|
|
17
68
|
property 'grade_smooth', transform_with: ->(v) { Strava::Models::Stream.new(v) }
|
|
18
69
|
end
|
|
19
70
|
end
|
|
@@ -2,67 +2,210 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents a summary view of a Strava activity.
|
|
7
|
+
#
|
|
8
|
+
# A summary activity contains the most important information about an activity
|
|
9
|
+
# without the detailed segments, splits, and other extended data found in
|
|
10
|
+
# {DetailedActivity}. This model is typically returned when listing activities
|
|
11
|
+
# or when full details are not needed.
|
|
12
|
+
#
|
|
13
|
+
# Includes helper mixins for formatting distance, time, elevation, speed, and sport type.
|
|
14
|
+
#
|
|
15
|
+
# @example List and display activities
|
|
16
|
+
# activities = client.athlete_activities(per_page: 10)
|
|
17
|
+
# activities.each do |activity|
|
|
18
|
+
# puts "#{activity.name} - #{activity.distance_s} in #{activity.moving_time_in_hours_s}"
|
|
19
|
+
# puts activity.strava_url
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# @see DetailedActivity
|
|
23
|
+
# @see https://developers.strava.com/docs/reference/#api-models-SummaryActivity
|
|
24
|
+
#
|
|
6
25
|
class SummaryActivity < Strava::Models::Response
|
|
26
|
+
# @return [Integer] Activity ID
|
|
7
27
|
property 'id'
|
|
28
|
+
|
|
29
|
+
# @return [String, nil] External ID from the original upload source
|
|
8
30
|
property 'external_id'
|
|
31
|
+
|
|
32
|
+
# @return [Integer, nil] Upload ID
|
|
9
33
|
property 'upload_id'
|
|
34
|
+
|
|
35
|
+
# @return [MetaAthlete] The athlete who performed the activity
|
|
10
36
|
property 'athlete', transform_with: ->(v) { Strava::Models::MetaAthlete.new(v) }
|
|
37
|
+
|
|
38
|
+
# @return [String] Activity name
|
|
11
39
|
property 'name'
|
|
40
|
+
|
|
12
41
|
include Mixins::Distance
|
|
13
42
|
include Mixins::MovingTime
|
|
14
43
|
include Mixins::ElapsedTime
|
|
15
44
|
include Mixins::TotalElevationGain
|
|
45
|
+
|
|
46
|
+
# @return [Float, nil] Highest elevation in meters
|
|
16
47
|
property 'elev_high'
|
|
48
|
+
|
|
49
|
+
# @return [Float, nil] Lowest elevation in meters
|
|
17
50
|
property 'elev_low'
|
|
51
|
+
|
|
18
52
|
include Mixins::SportType
|
|
53
|
+
|
|
54
|
+
# @return [Time] Start date and time (UTC)
|
|
19
55
|
property 'start_date', transform_with: ->(v) { Time.parse(v) }
|
|
56
|
+
|
|
20
57
|
include Mixins::StartDateLocal
|
|
58
|
+
|
|
59
|
+
# @return [String] Timezone in which the activity was recorded
|
|
21
60
|
property 'timezone'
|
|
61
|
+
|
|
62
|
+
# @return [LatLng, nil] Starting coordinates [latitude, longitude]
|
|
22
63
|
property 'start_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
|
|
64
|
+
|
|
65
|
+
# @return [LatLng, nil] Ending coordinates [latitude, longitude]
|
|
23
66
|
property 'end_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
|
|
67
|
+
|
|
68
|
+
# @return [Integer] Number of achievements (segment PRs, CRs, etc.)
|
|
24
69
|
property 'achievement_count'
|
|
70
|
+
|
|
71
|
+
# @return [Integer] Number of kudos received
|
|
25
72
|
property 'kudos_count'
|
|
73
|
+
|
|
74
|
+
# @return [Integer] Number of comments
|
|
26
75
|
property 'comment_count'
|
|
76
|
+
|
|
77
|
+
# @return [Integer] Number of athletes who participated (group activities)
|
|
27
78
|
property 'athlete_count'
|
|
79
|
+
|
|
80
|
+
# @return [Integer] Number of photos attached
|
|
28
81
|
property 'photo_count'
|
|
82
|
+
|
|
83
|
+
# @return [Integer] Total number of photos including Instagram
|
|
29
84
|
property 'total_photo_count'
|
|
85
|
+
|
|
86
|
+
# @return [Map] Activity map with polyline data
|
|
30
87
|
property 'map', transform_with: ->(v) { Strava::Models::Map.new(v) }
|
|
88
|
+
|
|
89
|
+
# @return [Boolean] Whether this activity was on a stationary trainer
|
|
31
90
|
property 'trainer'
|
|
91
|
+
|
|
92
|
+
# @return [Boolean] Whether this activity was a commute
|
|
32
93
|
property 'commute'
|
|
94
|
+
|
|
95
|
+
# @return [Boolean] Whether this activity was manually entered
|
|
33
96
|
property 'manual'
|
|
97
|
+
|
|
98
|
+
# @return [Boolean] Whether this activity is set to private
|
|
34
99
|
property 'private'
|
|
100
|
+
|
|
101
|
+
# @return [Boolean] Whether this activity has been flagged
|
|
35
102
|
property 'flagged'
|
|
103
|
+
|
|
104
|
+
# @return [Integer, nil] Workout type (e.g., 10 = Race, 11 = Workout)
|
|
36
105
|
property 'workout_type'
|
|
106
|
+
|
|
107
|
+
# @return [String, nil] Upload ID as a string
|
|
37
108
|
property 'upload_id_str'
|
|
109
|
+
|
|
110
|
+
# @return [Float] Average speed in meters per second
|
|
38
111
|
property 'average_speed'
|
|
112
|
+
|
|
113
|
+
# @return [Float] Maximum speed in meters per second
|
|
39
114
|
property 'max_speed'
|
|
115
|
+
|
|
116
|
+
# @return [Boolean] Whether the authenticated athlete has kudoed this activity
|
|
40
117
|
property 'has_kudoed'
|
|
118
|
+
|
|
119
|
+
# @return [Boolean] Whether to hide this activity from the home feed
|
|
41
120
|
property 'hide_from_home'
|
|
121
|
+
|
|
122
|
+
# @return [String, nil] Gear (bike/shoes) ID used for this activity
|
|
42
123
|
property 'gear_id'
|
|
124
|
+
|
|
125
|
+
# @return [Float, nil] Kilojoules of energy expended
|
|
43
126
|
property 'kilojoules'
|
|
127
|
+
|
|
128
|
+
# @return [Float, nil] Average power in watts
|
|
44
129
|
property 'average_watts'
|
|
130
|
+
|
|
131
|
+
# @return [Boolean, nil] Whether the watts are from a power meter (true) or estimated (false)
|
|
45
132
|
property 'device_watts'
|
|
133
|
+
|
|
134
|
+
# @return [Integer, nil] Maximum power in watts
|
|
46
135
|
property 'max_watts'
|
|
136
|
+
|
|
137
|
+
# @return [Integer, nil] Weighted average power in watts
|
|
47
138
|
property 'weighted_average_watts'
|
|
48
|
-
|
|
139
|
+
|
|
140
|
+
# @note Undocumented in official API
|
|
141
|
+
# @return [Integer, nil] Resource state indicator
|
|
49
142
|
property 'resource_state'
|
|
143
|
+
|
|
144
|
+
# @note Undocumented in official API
|
|
145
|
+
# @return [String, nil] Activity visibility setting (e.g., 'everyone', 'followers_only')
|
|
50
146
|
property 'visibility'
|
|
147
|
+
|
|
148
|
+
# @note Undocumented in official API
|
|
149
|
+
# @return [Float, nil] UTC offset in seconds
|
|
51
150
|
property 'utc_offset'
|
|
151
|
+
|
|
152
|
+
# @note Undocumented in official API
|
|
153
|
+
# @return [String, nil] City where the activity took place
|
|
52
154
|
property 'location_city'
|
|
155
|
+
|
|
156
|
+
# @note Undocumented in official API
|
|
157
|
+
# @return [String, nil] State/province where the activity took place
|
|
53
158
|
property 'location_state'
|
|
159
|
+
|
|
160
|
+
# @note Undocumented in official API
|
|
161
|
+
# @return [String, nil] Country where the activity took place
|
|
54
162
|
property 'location_country'
|
|
163
|
+
|
|
164
|
+
# @note Undocumented in official API
|
|
165
|
+
# @return [Float, nil] Average cadence (RPM for cycling, steps/minute for running)
|
|
55
166
|
property 'average_cadence'
|
|
167
|
+
|
|
168
|
+
# @note Undocumented in official API
|
|
169
|
+
# @return [Float, nil] Average temperature during the activity in Celsius
|
|
56
170
|
property 'average_temp'
|
|
171
|
+
|
|
172
|
+
# @note Undocumented in official API
|
|
173
|
+
# @return [Boolean, nil] Whether the activity has heart rate data
|
|
57
174
|
property 'has_heartrate'
|
|
175
|
+
|
|
176
|
+
# @note Undocumented in official API
|
|
177
|
+
# @return [Float, nil] Average heart rate in beats per minute
|
|
58
178
|
property 'average_heartrate'
|
|
179
|
+
|
|
180
|
+
# @note Undocumented in official API
|
|
181
|
+
# @return [Float, nil] Maximum heart rate in beats per minute
|
|
59
182
|
property 'max_heartrate'
|
|
183
|
+
|
|
184
|
+
# @note Undocumented in official API
|
|
185
|
+
# @return [Boolean, nil] Whether the athlete has opted out of heart rate display
|
|
60
186
|
property 'heartrate_opt_out'
|
|
187
|
+
|
|
188
|
+
# @note Undocumented in official API
|
|
189
|
+
# @return [Boolean, nil] Whether to display the hide heart rate option
|
|
61
190
|
property 'display_hide_heartrate_option'
|
|
191
|
+
|
|
192
|
+
# @note Undocumented in official API
|
|
193
|
+
# @return [Boolean, nil] Whether the activity was created from an accepted tag
|
|
62
194
|
property 'from_accepted_tag'
|
|
195
|
+
|
|
196
|
+
# @note Undocumented in official API
|
|
197
|
+
# @return [Integer, nil] Number of personal records achieved in this activity
|
|
63
198
|
property 'pr_count'
|
|
199
|
+
|
|
200
|
+
# @note Undocumented in official API
|
|
201
|
+
# @return [Integer, nil] Relative effort score (suffer score)
|
|
64
202
|
property 'suffer_score'
|
|
65
203
|
|
|
204
|
+
#
|
|
205
|
+
# Returns the Strava web URL for this activity.
|
|
206
|
+
#
|
|
207
|
+
# @return [String] Full URL to view the activity on Strava.com
|
|
208
|
+
#
|
|
66
209
|
def strava_url
|
|
67
210
|
"https://www.strava.com/activities/#{id}"
|
|
68
211
|
end
|
|
@@ -2,27 +2,80 @@
|
|
|
2
2
|
|
|
3
3
|
module Strava
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
#
|
|
6
|
+
# Represents summary information about a Strava athlete.
|
|
7
|
+
#
|
|
8
|
+
# Contains basic profile information about an athlete. This is typically returned
|
|
9
|
+
# when listing kudoers, commenters, or other athletes associated with activities,
|
|
10
|
+
# rather than the full {DetailedAthlete} information.
|
|
11
|
+
#
|
|
12
|
+
# @example Access athlete who kudoed an activity
|
|
13
|
+
# kudoers = client.activity_kudos(1234567890)
|
|
14
|
+
# kudoers.each do |athlete|
|
|
15
|
+
# puts "#{athlete.name} from #{athlete.city}"
|
|
16
|
+
# puts athlete.strava_url
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# @see DetailedAthlete
|
|
20
|
+
# @see https://developers.strava.com/docs/reference/#api-models-SummaryAthlete
|
|
21
|
+
#
|
|
6
22
|
class SummaryAthlete < Strava::Models::Response
|
|
23
|
+
# @return [Integer] Athlete ID
|
|
7
24
|
property 'id'
|
|
25
|
+
|
|
26
|
+
# @return [Integer] Resource state indicator
|
|
8
27
|
property 'resource_state'
|
|
28
|
+
|
|
29
|
+
# @return [String] First name
|
|
9
30
|
property 'firstname'
|
|
31
|
+
|
|
32
|
+
# @return [String] Last name
|
|
10
33
|
property 'lastname'
|
|
34
|
+
|
|
35
|
+
# @return [String, nil] URL to medium-sized profile picture
|
|
11
36
|
property 'profile_medium'
|
|
37
|
+
|
|
38
|
+
# @return [String, nil] URL to full-sized profile picture
|
|
12
39
|
property 'profile'
|
|
40
|
+
|
|
41
|
+
# @return [String, nil] City
|
|
13
42
|
property 'city'
|
|
43
|
+
|
|
44
|
+
# @return [String, nil] State or province
|
|
14
45
|
property 'state'
|
|
46
|
+
|
|
47
|
+
# @return [String, nil] Country
|
|
15
48
|
property 'country'
|
|
49
|
+
|
|
50
|
+
# @return [String] Sex ('M' for male, 'F' for female)
|
|
16
51
|
property 'sex'
|
|
52
|
+
|
|
53
|
+
# @return [Boolean] Whether the athlete has a premium subscription
|
|
17
54
|
property 'premium'
|
|
55
|
+
|
|
56
|
+
# @return [Boolean] Whether the athlete has a Summit subscription
|
|
18
57
|
property 'summit'
|
|
58
|
+
|
|
59
|
+
# @return [Time] When the athlete account was created
|
|
19
60
|
property 'created_at', transform_with: ->(v) { Time.parse(v) }
|
|
61
|
+
|
|
62
|
+
# @return [Time] When the athlete account was last updated
|
|
20
63
|
property 'updated_at', transform_with: ->(v) { Time.parse(v) }
|
|
21
64
|
|
|
65
|
+
#
|
|
66
|
+
# Returns the athlete's full name.
|
|
67
|
+
#
|
|
68
|
+
# @return [String, nil] Full name combining firstname and lastname, or nil if neither exists
|
|
69
|
+
#
|
|
22
70
|
def name
|
|
23
71
|
[firstname, lastname].compact.join(' ') if firstname || lastname
|
|
24
72
|
end
|
|
25
73
|
|
|
74
|
+
#
|
|
75
|
+
# Returns the Strava web URL for this athlete's profile.
|
|
76
|
+
#
|
|
77
|
+
# @return [String] Full URL to view the athlete on Strava.com
|
|
78
|
+
#
|
|
26
79
|
def strava_url
|
|
27
80
|
"https://www.strava.com/athletes/#{id}"
|
|
28
81
|
end
|