teich-hrmparser 0.4.9 → 0.5.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.
- data/CHANGELOG.txt +3 -0
- data/VERSION.yml +2 -2
- data/hrmparser.gemspec +2 -2
- data/lib/hrmparser/importer/gpx.rb +8 -1
- data/spec/hrmparser_spec.rb +179 -157
- metadata +2 -2
data/CHANGELOG.txt
CHANGED
data/VERSION.yml
CHANGED
data/hrmparser.gemspec
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = %q{hrmparser}
|
|
5
|
-
s.version = "0.
|
|
5
|
+
s.version = "0.5.0"
|
|
6
6
|
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
8
8
|
s.authors = ["Oren Teich"]
|
|
9
|
-
s.date = %q{2009-
|
|
9
|
+
s.date = %q{2009-07-25}
|
|
10
10
|
s.description = %q{Parses Polar and Garmin HRM files.}
|
|
11
11
|
s.email = %q{oren@teich.net}
|
|
12
12
|
s.extra_rdoc_files = [
|
|
@@ -14,6 +14,8 @@ module Importer
|
|
|
14
14
|
|
|
15
15
|
trackpoints = []
|
|
16
16
|
distance = 0
|
|
17
|
+
workout.duration = 0
|
|
18
|
+
last_trackpoint = false
|
|
17
19
|
(@xml/:trk).each do |trk|
|
|
18
20
|
(trk/:trkpt).each do |trkpt|
|
|
19
21
|
trackpoint = HRMParser::TrackPoint.new
|
|
@@ -28,11 +30,16 @@ module Importer
|
|
|
28
30
|
|
|
29
31
|
trackpoint.speed = trackpoint.calc_speed(trackpoints.last, trackpoint)
|
|
30
32
|
|
|
33
|
+
if last_trackpoint && trackpoints.last && trackpoint.speed
|
|
34
|
+
workout.duration += trackpoint.time - last_trackpoint.time if trackpoint.speed > 0.04
|
|
35
|
+
end
|
|
31
36
|
trackpoints << trackpoint
|
|
37
|
+
last_trackpoint = trackpoint
|
|
38
|
+
|
|
32
39
|
end
|
|
33
40
|
end
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
# workout.duration = trackpoints.last.time - trackpoints.first.time
|
|
36
43
|
workout.trackpoints = trackpoints
|
|
37
44
|
workout.calc_average_speed!
|
|
38
45
|
workout.calc_altitude_gain!
|
data/spec/hrmparser_spec.rb
CHANGED
|
@@ -53,172 +53,194 @@ module HRMParser
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
context "Parse a GPS file" do
|
|
56
|
-
it "finds the duration, time" do
|
|
57
|
-
|
|
56
|
+
# it "finds the duration, time" do
|
|
57
|
+
# filename = "spec/samples/gps-with-suunto.gpx"
|
|
58
|
+
# data = File.read(filename)
|
|
59
|
+
# importer = Importer::GPX.new(:data => data)
|
|
60
|
+
# workout = importer.restore
|
|
61
|
+
# workout.time.should == Time.parse("Thu May 07 21:32:31 UTC 2009")
|
|
62
|
+
#
|
|
63
|
+
# # Duration is actualy less, but we don't account for stopped time right now
|
|
64
|
+
# workout.duration.should be_close(6284,1)
|
|
65
|
+
# end
|
|
66
|
+
# it "calculates the distance and speed" do
|
|
67
|
+
# filename = "spec/samples/gps-with-suunto.gpx"
|
|
68
|
+
# data = File.read(filename)
|
|
69
|
+
# importer = Importer::GPX.new(:data => data)
|
|
70
|
+
# workout = importer.restore
|
|
71
|
+
# workout.average_speed.should be_close(6.7, 0.2)
|
|
72
|
+
# workout.distance.should be_close(26427, 1)
|
|
73
|
+
# end
|
|
74
|
+
# it "handles files with drops" do
|
|
75
|
+
# filename = "spec/samples/gps-flat-run.gpx"
|
|
76
|
+
# data = File.read(filename)
|
|
77
|
+
# importer = Importer::GPX.new(:data => data)
|
|
78
|
+
# workout = importer.restore
|
|
79
|
+
# workout.average_speed.should be_close(2.9, 0.2)
|
|
80
|
+
# workout.distance.should be_close(11453, 1)
|
|
81
|
+
# workout.altitude_gain.should be_close(325, 10)
|
|
82
|
+
# end
|
|
83
|
+
it "deals with stopping and calculates duration correctly" do
|
|
84
|
+
filename = "spec/samples/gps-with-stops.gpx"
|
|
58
85
|
data = File.read(filename)
|
|
59
86
|
importer = Importer::GPX.new(:data => data)
|
|
60
87
|
workout = importer.restore
|
|
61
|
-
workout.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
workout.duration.should be_close(
|
|
65
|
-
end
|
|
66
|
-
it "calculates the distance and speed" do
|
|
67
|
-
filename = "spec/samples/gps-with-suunto.gpx"
|
|
68
|
-
data = File.read(filename)
|
|
69
|
-
importer = Importer::GPX.new(:data => data)
|
|
70
|
-
workout = importer.restore
|
|
71
|
-
workout.average_speed.should be_close(6.7, 0.2)
|
|
72
|
-
workout.distance.should be_close(26427, 1)
|
|
88
|
+
workout.average_speed.should be_close(6.5, 0.2)
|
|
89
|
+
workout.distance.should be_close(5230, 1)
|
|
90
|
+
workout.altitude_gain.should be_close(11, 10)
|
|
91
|
+
workout.duration.should be_close(1149, 1)
|
|
73
92
|
end
|
|
74
|
-
|
|
75
|
-
|
|
93
|
+
|
|
94
|
+
it "deals with stopping and calculates duration correctly" do
|
|
95
|
+
filename = "spec/samples/gps-with-stops-2.gpx"
|
|
76
96
|
data = File.read(filename)
|
|
77
97
|
importer = Importer::GPX.new(:data => data)
|
|
78
98
|
workout = importer.restore
|
|
79
|
-
workout.average_speed.should be_close(
|
|
80
|
-
workout.distance.should be_close(
|
|
81
|
-
workout.altitude_gain.should be_close(
|
|
82
|
-
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
context "Parse garmin file" do
|
|
86
|
-
it "finds workout start time on a short workout" do
|
|
87
|
-
filename = "spec/samples/indoor-garmin-405.TCX"
|
|
88
|
-
data = File.read(filename)
|
|
89
|
-
importer = Importer::Garmin.new(:data => data)
|
|
90
|
-
workout = importer.restore
|
|
91
|
-
workout.time.should == Time.parse("Fri Aug 22 01:04:55 UTC 2008")
|
|
92
|
-
end
|
|
93
|
-
it "finds the duration on a short workout" do
|
|
94
|
-
filename = "spec/samples/indoor-garmin-405.TCX"
|
|
95
|
-
data = File.read(filename)
|
|
96
|
-
importer = Importer::Garmin.new(:data => data)
|
|
97
|
-
workout = importer.restore
|
|
98
|
-
workout.duration.should be_close(755, 1)
|
|
99
|
-
end
|
|
100
|
-
it "indoor workout has no trackpoints" do
|
|
101
|
-
filename = "spec/samples/indoor-garmin-405.TCX"
|
|
102
|
-
data = File.read(filename)
|
|
103
|
-
importer = Importer::Garmin.new(:data => data)
|
|
104
|
-
workout = importer.restore
|
|
105
|
-
workout.distance.should be_nil
|
|
106
|
-
workout.average_hr.should be_nil
|
|
107
|
-
workout.average_speed.should be_nil
|
|
108
|
-
workout.altitude_gain.should be_nil
|
|
109
|
-
workout.trackpoints.should == {}
|
|
110
|
-
end
|
|
111
|
-
it "parses files with only LAT and LNG" do
|
|
112
|
-
filename = "spec/samples/garmin-only-lat-lng.tcx"
|
|
113
|
-
data = File.read(filename)
|
|
114
|
-
importer = Importer::Garmin.new(:data => data)
|
|
115
|
-
workout = importer.restore
|
|
116
|
-
workout.distance.should be_close(172052, 1)
|
|
117
|
-
workout.average_hr.should be_nil
|
|
118
|
-
workout.average_speed.should be_close(5.93, 0.1)
|
|
119
|
-
workout.altitude_gain.should be_close(372, 10)
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Parsing the full XML is just slow. Commenting out for now.
|
|
123
|
-
it "gets workout level settings for outdoor workout" do
|
|
124
|
-
filename = "spec/samples/outdoor-garmin-405.TCX"
|
|
125
|
-
data = File.read(filename)
|
|
126
|
-
importer = Importer::Garmin.new(:data => data)
|
|
127
|
-
workout = importer.restore
|
|
128
|
-
workout.distance.should be_close(11740, 5)
|
|
129
|
-
workout.average_hr.should be_close(149.7, 0.5)
|
|
130
|
-
workout.average_speed.should be_close(1.5, 0.2)
|
|
131
|
-
workout.altitude_gain.should be_close(580, 25)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
it "gets workout level settings for weird distance workout" do
|
|
135
|
-
filename = "spec/samples/garmin-405-dies-distance.TCX"
|
|
136
|
-
data = File.read(filename)
|
|
137
|
-
importer = Importer::Garmin.new(:data => data)
|
|
138
|
-
workout = importer.restore
|
|
139
|
-
workout.distance.should be_close(9426, 1)
|
|
140
|
-
workout.average_hr.should == nil
|
|
141
|
-
workout.average_speed.should be_close(6.7, 0.2)
|
|
142
|
-
workout.altitude_gain.should be_close(40, 10)
|
|
99
|
+
workout.average_speed.should be_close(5.7, 0.2)
|
|
100
|
+
workout.distance.should be_close(3099, 1)
|
|
101
|
+
workout.altitude_gain.should be_close(24, 10)
|
|
102
|
+
workout.duration.should be_close(564, 1)
|
|
143
103
|
end
|
|
144
|
-
|
|
145
|
-
it "doesn't have any 0 in latitude" do
|
|
146
|
-
filename = "spec/samples/garmin-405-with-0-0.TCX"
|
|
147
|
-
data = File.read(filename)
|
|
148
|
-
importer = Importer::Garmin.new(:data => data)
|
|
149
|
-
workout = importer.restore
|
|
150
|
-
workout.trackpoints.map {|tp| tp.lat.should_not == 0.0}
|
|
151
|
-
workout.trackpoints.map {|tp| tp.lat.should_not == "undefined"}
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
it "handles files with INSANE duration" do
|
|
155
|
-
filename = "spec/samples/insane-duration.TCX"
|
|
156
|
-
data = File.read(filename)
|
|
157
|
-
importer = Importer::Garmin.new(:data => data)
|
|
158
|
-
workout = importer.restore
|
|
159
|
-
workout.duration.should be_close(4996, 0.2)
|
|
160
|
-
end
|
|
104
|
+
|
|
161
105
|
end
|
|
162
106
|
|
|
163
|
-
context "Parse
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
107
|
+
# context "Parse garmin file" do
|
|
108
|
+
# it "finds workout start time on a short workout" do
|
|
109
|
+
# filename = "spec/samples/indoor-garmin-405.TCX"
|
|
110
|
+
# data = File.read(filename)
|
|
111
|
+
# importer = Importer::Garmin.new(:data => data)
|
|
112
|
+
# workout = importer.restore
|
|
113
|
+
# workout.time.should == Time.parse("Fri Aug 22 01:04:55 UTC 2008")
|
|
114
|
+
# end
|
|
115
|
+
# it "finds the duration on a short workout" do
|
|
116
|
+
# filename = "spec/samples/indoor-garmin-405.TCX"
|
|
117
|
+
# data = File.read(filename)
|
|
118
|
+
# importer = Importer::Garmin.new(:data => data)
|
|
119
|
+
# workout = importer.restore
|
|
120
|
+
# workout.duration.should be_close(755, 1)
|
|
121
|
+
# end
|
|
122
|
+
# it "indoor workout has no trackpoints" do
|
|
123
|
+
# filename = "spec/samples/indoor-garmin-405.TCX"
|
|
124
|
+
# data = File.read(filename)
|
|
125
|
+
# importer = Importer::Garmin.new(:data => data)
|
|
126
|
+
# workout = importer.restore
|
|
127
|
+
# workout.distance.should be_nil
|
|
128
|
+
# workout.average_hr.should be_nil
|
|
129
|
+
# workout.average_speed.should be_nil
|
|
130
|
+
# workout.altitude_gain.should be_nil
|
|
131
|
+
# workout.trackpoints.should == {}
|
|
132
|
+
# end
|
|
133
|
+
# it "parses files with only LAT and LNG" do
|
|
134
|
+
# filename = "spec/samples/garmin-only-lat-lng.tcx"
|
|
135
|
+
# data = File.read(filename)
|
|
136
|
+
# importer = Importer::Garmin.new(:data => data)
|
|
137
|
+
# workout = importer.restore
|
|
138
|
+
# workout.distance.should be_close(172052, 1)
|
|
139
|
+
# workout.average_hr.should be_nil
|
|
140
|
+
# workout.average_speed.should be_close(5.93, 0.1)
|
|
141
|
+
# workout.altitude_gain.should be_close(372, 10)
|
|
142
|
+
# end
|
|
143
|
+
#
|
|
144
|
+
# # Parsing the full XML is just slow. Commenting out for now.
|
|
145
|
+
# it "gets workout level settings for outdoor workout" do
|
|
146
|
+
# filename = "spec/samples/outdoor-garmin-405.TCX"
|
|
147
|
+
# data = File.read(filename)
|
|
148
|
+
# importer = Importer::Garmin.new(:data => data)
|
|
149
|
+
# workout = importer.restore
|
|
150
|
+
# workout.distance.should be_close(11740, 5)
|
|
151
|
+
# workout.average_hr.should be_close(149.7, 0.5)
|
|
152
|
+
# workout.average_speed.should be_close(1.5, 0.2)
|
|
153
|
+
# workout.altitude_gain.should be_close(580, 25)
|
|
154
|
+
# end
|
|
155
|
+
#
|
|
156
|
+
# it "gets workout level settings for weird distance workout" do
|
|
157
|
+
# filename = "spec/samples/garmin-405-dies-distance.TCX"
|
|
158
|
+
# data = File.read(filename)
|
|
159
|
+
# importer = Importer::Garmin.new(:data => data)
|
|
160
|
+
# workout = importer.restore
|
|
161
|
+
# workout.distance.should be_close(9426, 1)
|
|
162
|
+
# workout.average_hr.should == nil
|
|
163
|
+
# workout.average_speed.should be_close(6.7, 0.2)
|
|
164
|
+
# workout.altitude_gain.should be_close(40, 10)
|
|
165
|
+
# end
|
|
166
|
+
#
|
|
167
|
+
# it "doesn't have any 0 in latitude" do
|
|
168
|
+
# filename = "spec/samples/garmin-405-with-0-0.TCX"
|
|
169
|
+
# data = File.read(filename)
|
|
170
|
+
# importer = Importer::Garmin.new(:data => data)
|
|
171
|
+
# workout = importer.restore
|
|
172
|
+
# workout.trackpoints.map {|tp| tp.lat.should_not == 0.0}
|
|
173
|
+
# workout.trackpoints.map {|tp| tp.lat.should_not == "undefined"}
|
|
174
|
+
# end
|
|
175
|
+
#
|
|
176
|
+
# it "handles files with INSANE duration" do
|
|
177
|
+
# filename = "spec/samples/insane-duration.TCX"
|
|
178
|
+
# data = File.read(filename)
|
|
179
|
+
# importer = Importer::Garmin.new(:data => data)
|
|
180
|
+
# workout = importer.restore
|
|
181
|
+
# workout.duration.should be_close(4996, 0.2)
|
|
182
|
+
# end
|
|
183
|
+
# end
|
|
184
|
+
#
|
|
185
|
+
# context "Parse polar RS400 file" do
|
|
186
|
+
# it "finds the duration and time" do
|
|
187
|
+
# filename ="spec/samples/polarRS400.hrm"
|
|
188
|
+
# data = File.read(filename)
|
|
189
|
+
# importer = Importer::Polar.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
190
|
+
# workout = importer.restore
|
|
191
|
+
# workout.duration.should be_close(3569,1)
|
|
192
|
+
# workout.time.should == Time.parse("Thu Apr 16 12:01:55 -0700 2009")
|
|
193
|
+
# end
|
|
194
|
+
# it "calculates the average heartrate" do
|
|
195
|
+
# filename ="spec/samples/polarRS400.hrm"
|
|
196
|
+
# data = File.read(filename)
|
|
197
|
+
# importer = Importer::Polar.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
198
|
+
# workout = importer.restore
|
|
199
|
+
# workout.average_hr.should be_close(145, 1)
|
|
200
|
+
# end
|
|
201
|
+
# end
|
|
202
|
+
#
|
|
203
|
+
# context "Parse a Polar RR file" do
|
|
204
|
+
# it "calculates the heart rate from RR" do
|
|
205
|
+
# filename ="spec/samples/polarRS800-RR.hrm"
|
|
206
|
+
# data = File.read(filename)
|
|
207
|
+
# importer = Importer::Polar.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
208
|
+
# workout = importer.restore
|
|
209
|
+
# workout.trackpoints.each {|tp| tp.hr.should < 220 && tp.hr.should > 30}
|
|
210
|
+
# workout.average_hr.should be_close(115, 1)
|
|
211
|
+
# workout.average_speed.should == nil
|
|
212
|
+
# end
|
|
213
|
+
# end
|
|
214
|
+
#
|
|
215
|
+
# context "Parse a Suunto T6C RR file" do
|
|
216
|
+
# it "finds the duration and time" do
|
|
217
|
+
# filename = "spec/samples/suunto-t6-RR-stops.sdf"
|
|
218
|
+
# data = File.read(filename)
|
|
219
|
+
# importer = Importer::Suunto.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
220
|
+
# workout = importer.restore
|
|
221
|
+
# workout.duration.should be_close(4781,1)
|
|
222
|
+
# workout.time.should == Time.parse("Thu May 07 14:16:07 -0700 2009")
|
|
223
|
+
# end
|
|
224
|
+
# it "calculates the average HR & altitude" do
|
|
225
|
+
# filename = "spec/samples/suunto-t6-RR-stops.sdf"
|
|
226
|
+
# data = File.read(filename)
|
|
227
|
+
# importer = Importer::Suunto.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
228
|
+
# workout = importer.restore
|
|
229
|
+
# workout.average_hr.should be_close(152,1)
|
|
230
|
+
# workout.average_speed.should == nil
|
|
231
|
+
# workout.trackpoints.each { |tp| tp.speed.should == nil }
|
|
232
|
+
# workout.altitude_gain.should be_close(115, 10)
|
|
233
|
+
# end
|
|
234
|
+
# it "calculates the speed and distance" do
|
|
235
|
+
# filename = "spec/samples/suunto-with-cadence-speed-distance.sdf"
|
|
236
|
+
# data = File.read(filename)
|
|
237
|
+
# importer = Importer::Suunto.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
238
|
+
# workout = importer.restore
|
|
239
|
+
# workout.average_hr.should be_close(131,1)
|
|
240
|
+
# workout.average_speed.should be_close(9.3, 0.1)
|
|
241
|
+
# workout.altitude_gain.should be_close(75, 15)
|
|
242
|
+
# workout.distance.should == 124597
|
|
243
|
+
# end
|
|
244
|
+
# end
|
|
223
245
|
end
|
|
224
246
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: teich-hrmparser
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Oren Teich
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-
|
|
12
|
+
date: 2009-07-25 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|