tcxread 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -1
  3. data/lib/tcxread.rb +67 -53
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed1afce3cee9d915fdabd00e0732caafa749719188118bbe428ddf7eadd3f52d
4
- data.tar.gz: a3867ff511e74ea4e2b11efbdcfcf36d453e5b1030a4d5c28bd1ef10ac70a76f
3
+ metadata.gz: 7b17178126aaf26d70869aa047a6054ca4128ac454c75b3fbd0903ce935222dc
4
+ data.tar.gz: f27e41c68c87672a7acd2791b4a147c8a0bf09a2da1707a8722091a965508b89
5
5
  SHA512:
6
- metadata.gz: 0666fd2bd6601145ad998911252e4856f9e4e6d8eca9673dd2f4076c3fc0abff1cd2264a3521a5602771f4a4d16914a9ded05f678d08c8ca04efef138effbcc9
7
- data.tar.gz: aa6bc442fe648352928bf01710b98ba37faca036c5e0be103fbef453e7edafe0da1060bf955fd66f206da97e048e40031f35878b45fe881e517c681ea062ab0f
6
+ metadata.gz: 9281010f7900f5bf0a579c648690329e0f5680ecb9cc91e56733a2718ce15ac75cdfa15eabb4fc4f97b99d6cd26dfbbb53c627124775261fa1083797f9c1d4c1
7
+ data.tar.gz: c61eee523a2b34730e40cddce7cd2eb58193bcb9585b84c0d08252f66cd8f4e90f49b6bf77dcbebdf13d8e96336fd5365787a3e670fda68b26cab214a540cd26
data/README.md CHANGED
@@ -49,7 +49,11 @@ puts "Distance meters: #{data.total_distance_meters}, " \
49
49
  "Average heart rate: #{data.average_heart_rate}, " \
50
50
  "Average watts: #{data.average_watts}, " \
51
51
  "Max watts: #{data.max_watts}, " \
52
- "Average cadence: #{data.average_cadence}"
52
+ "Average speed: #{data.average_speed_all}, " \
53
+ "Average speed (moving): #{data.average_speed_moving}, " \
54
+ "Average cadence (moving): #{data.average_cadence_biking}, " \
55
+ "Average cadence: #{data.average_cadence_all}"
56
+
53
57
  ```
54
58
 
55
59
  ## 💾 Datasets
data/lib/tcxread.rb CHANGED
@@ -1,11 +1,10 @@
1
1
  require "nokogiri"
2
2
 
3
- # TCXRead is a class that parses TCX (Training Center XML) files to extract
4
- # workout data such as activities, laps, tracks, trackpoints, and integral metrics.
5
3
  class TCXRead
6
4
  attr_reader :total_distance_meters, :total_time_seconds, :total_calories,
7
5
  :total_ascent, :total_descent, :max_altitude, :average_heart_rate,
8
- :max_watts, :average_watts, :average_cadence
6
+ :max_watts, :average_watts, :average_cadence_all, :average_cadence_biking,
7
+ :average_speed_all, :average_speed_moving
9
8
 
10
9
  def initialize(file_path)
11
10
  @file_path = file_path
@@ -19,17 +18,16 @@ class TCXRead
19
18
  @total_descent = 0
20
19
  @max_altitude = 0
21
20
  @average_heart_rate = 0
22
- # use NA if no watts exist in the TCX file
23
21
  @max_watts = 'NA'
24
22
  @average_watts = 'NA'
25
- @average_cadence = 0
23
+ @average_cadence_all = 0
24
+ @average_cadence_biking = 0
25
+ @average_speed_all = 0
26
+ @average_speed_moving = 0
26
27
 
27
28
  parse
28
29
  end
29
30
 
30
- # Parses the TCX file and extracts data.
31
- #
32
- # @return [Hash] a hash containing the parsed activities.
33
31
  def parse
34
32
  activities = parse_activities
35
33
  if activities.any?
@@ -39,7 +37,12 @@ class TCXRead
39
37
  @total_ascent, @total_descent, @max_altitude = calculate_ascent_descent_and_max_altitude_from_activities(activities)
40
38
  @average_heart_rate = calculate_average_heart_rate_from_activities(activities)
41
39
  @max_watts, @average_watts = calculate_watts_from_activities(activities)
42
- @average_cadence = calculate_average_cadence_from_activities(activities)
40
+ cadence_results = calculate_average_cadence_from_activities(activities)
41
+ @average_cadence_all = cadence_results[:average_cadence_all]
42
+ @average_cadence_biking = cadence_results[:average_cadence_biking]
43
+ speed_results = calculate_average_speed_from_activities(activities)
44
+ @average_speed_all = speed_results[:average_speed_all]
45
+ @average_speed_moving = speed_results[:average_speed_moving]
43
46
  end
44
47
 
45
48
  { activities: activities }
@@ -47,9 +50,6 @@ class TCXRead
47
50
 
48
51
  private
49
52
 
50
- # Parses the activities from the TCX file.
51
- #
52
- # @return [Array<Hash>] an array of hashes, each representing an activity.
53
53
  def parse_activities
54
54
  activities = []
55
55
  @doc.xpath('//xmlns:Activities/xmlns:Activity').each do |activity|
@@ -76,10 +76,6 @@ class TCXRead
76
76
  activities
77
77
  end
78
78
 
79
- # Parses the laps for a given activity.
80
- #
81
- # @param activity [Nokogiri::XML::Element] the activity element from the TCX file.
82
- # @return [Array<Hash>] an array of hashes, each representing a lap.
83
79
  def parse_laps(activity)
84
80
  laps = []
85
81
  activity.xpath('xmlns:Lap').each do |lap|
@@ -100,10 +96,6 @@ class TCXRead
100
96
  laps
101
97
  end
102
98
 
103
- # Parses the tracks for a given lap.
104
- #
105
- # @param lap [Nokogiri::XML::Element] the lap element from the TCX file.
106
- # @return [Array<Array<Hash>>] an array of arrays, each representing a track containing trackpoints.
107
99
  def parse_tracks(lap)
108
100
  tracks = []
109
101
  lap.xpath('xmlns:Track').each do |track|
@@ -125,10 +117,6 @@ class TCXRead
125
117
  tracks
126
118
  end
127
119
 
128
- # Parses the position for a given trackpoint.
129
- #
130
- # @param trackpoint [Nokogiri::XML::Element] the trackpoint element from the TCX file.
131
- # @return [Hash, nil] a hash representing the position (latitude and longitude) or nil if no position is available.
132
120
  def parse_position(trackpoint)
133
121
  position = trackpoint.at_xpath('xmlns:Position')
134
122
  return nil unless position
@@ -139,10 +127,6 @@ class TCXRead
139
127
  }
140
128
  end
141
129
 
142
- # Calculates the total ascent, total descent, and maximum altitude from the laps.
143
- #
144
- # @param laps [Array<Hash>] an array of lap hashes.
145
- # @return [Array<Float>] an array containing total ascent, total descent, and maximum altitude.
146
130
  def calculate_ascent_descent_and_max_altitude(laps)
147
131
  total_ascent = 0.0
148
132
  total_descent = 0.0
@@ -170,10 +154,6 @@ class TCXRead
170
154
  [total_ascent, total_descent, max_altitude]
171
155
  end
172
156
 
173
- # Calculates the total ascent, total descent, and maximum altitude from the activities.
174
- #
175
- # @param activities [Array<Hash>] an array of activity hashes.
176
- # @return [Array<Float>] an array containing total ascent, total descent, and maximum altitude.
177
157
  def calculate_ascent_descent_and_max_altitude_from_activities(activities)
178
158
  total_ascent = 0.0
179
159
  total_descent = 0.0
@@ -188,10 +168,6 @@ class TCXRead
188
168
  [total_ascent, total_descent, max_altitude]
189
169
  end
190
170
 
191
- # Calculates the average heart rate from the laps.
192
- #
193
- # @param laps [Array<Hash>] an array of lap hashes.
194
- # @return [Float] the average heart rate.
195
171
  def calculate_average_heart_rate(laps)
196
172
  total_heart_rate = 0
197
173
  heart_rate_count = 0
@@ -209,10 +185,6 @@ class TCXRead
209
185
  heart_rate_count > 0 ? total_heart_rate.to_f / heart_rate_count : 0.0
210
186
  end
211
187
 
212
- # Calculates the average heart rate from the activities.
213
- #
214
- # @param activities [Array<Hash>] an array of activity hashes.
215
- # @return [Float] the average heart rate.
216
188
  def calculate_average_heart_rate_from_activities(activities)
217
189
  total_heart_rate = 0
218
190
  heart_rate_count = 0
@@ -232,10 +204,6 @@ class TCXRead
232
204
  heart_rate_count > 0 ? total_heart_rate.to_f / heart_rate_count : 0.0
233
205
  end
234
206
 
235
- # Calculates the maximum and average watts from the activities.
236
- #
237
- # @param activities [Array<Hash>] an array of activity hashes.
238
- # @return [Array<Float, Float>] an array containing maximum watts and average watts. Returns 'NA' for both if no watts data is available.
239
207
  def calculate_watts_from_activities(activities)
240
208
  max_watts = 0
241
209
  total_watts = 0
@@ -265,26 +233,72 @@ class TCXRead
265
233
  [max_watts, average_watts]
266
234
  end
267
235
 
268
- # Calculates the average cadence from the activities.
269
- #
270
- # @param activities [Array<Hash>] an array of activity hashes.
271
- # @return [Float] the average cadence.
272
236
  def calculate_average_cadence_from_activities(activities)
273
- total_cadence = 0
274
- cadence_count = 0
237
+ total_cadence_all = 0
238
+ total_cadence_biking = 0
239
+ cadence_count_all = 0
240
+ cadence_count_biking = 0
275
241
 
276
242
  activities.each do |activity|
277
243
  activity[:laps].each do |lap|
278
244
  lap[:tracks].flatten.each do |trackpoint|
279
245
  cadence = trackpoint[:cadence]
246
+ total_cadence_all += cadence
247
+ cadence_count_all += 1
248
+
280
249
  if cadence > 0
281
- total_cadence += cadence
282
- cadence_count += 1
250
+ total_cadence_biking += cadence
251
+ cadence_count_biking += 1
283
252
  end
284
253
  end
285
254
  end
286
255
  end
287
256
 
288
- cadence_count > 0 ? total_cadence.to_f / cadence_count : 0.0
257
+ average_cadence_all = cadence_count_all > 0 ? total_cadence_all.to_f / cadence_count_all : 0.0
258
+ average_cadence_biking = cadence_count_biking > 0 ? total_cadence_biking.to_f / cadence_count_biking : 0.0
259
+
260
+ {
261
+ average_cadence_all: average_cadence_all,
262
+ average_cadence_biking: average_cadence_biking
263
+ }
264
+ end
265
+
266
+ # Calculates the average speed from the activities.
267
+ #
268
+ # @param activities [Array<Hash>] an array of activity hashes.
269
+ # @return [Hash] a hash containing average speed including zeros and average speed while moving.
270
+ def calculate_average_speed_from_activities(activities)
271
+ total_speed_all = 0
272
+ total_speed_moving = 0
273
+ speed_count_all = 0
274
+ speed_count_moving = 0
275
+
276
+ activities.each do |activity|
277
+ activity[:laps].each do |lap|
278
+ lap[:tracks].flatten.each do |trackpoint|
279
+ distance = trackpoint[:distance_meters]
280
+ time_seconds = lap[:total_time_seconds]
281
+ speed = distance / time_seconds if time_seconds > 0
282
+
283
+ if speed
284
+ total_speed_all += speed
285
+ speed_count_all += 1
286
+
287
+ if speed > 0
288
+ total_speed_moving += speed
289
+ speed_count_moving += 1
290
+ end
291
+ end
292
+ end
293
+ end
294
+ end
295
+
296
+ average_speed_all = speed_count_all > 0 ? total_speed_all.to_f / speed_count_all : 0.0
297
+ average_speed_moving = speed_count_moving > 0 ? total_speed_moving.to_f / speed_count_moving : 0.0
298
+
299
+ {
300
+ average_speed_all: average_speed_all,
301
+ average_speed_moving: average_speed_moving
302
+ }
289
303
  end
290
304
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tcxread
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - firefly-cpp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-11 00:00:00.000000000 Z
11
+ date: 2024-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri