teich-hrmparser 0.4.8 → 0.4.9
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 +1 -1
- data/hrmparser.gemspec +2 -2
- data/lib/hrmparser/importer/garmin.rb +28 -20
- data/lib/hrmparser/trackpoint.rb +3 -2
- data/spec/hrmparser_spec.rb +83 -75
- 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.4.
|
|
5
|
+
s.version = "0.4.9"
|
|
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-06-10}
|
|
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 = [
|
|
@@ -23,6 +23,8 @@ module Importer
|
|
|
23
23
|
distance_one = nil
|
|
24
24
|
time_one = nil
|
|
25
25
|
|
|
26
|
+
totaldistance = 0
|
|
27
|
+
|
|
26
28
|
(@xml/:Trackpoint).each do |t|
|
|
27
29
|
found = true
|
|
28
30
|
trackpoint = HRMParser::TrackPoint.new
|
|
@@ -38,31 +40,37 @@ module Importer
|
|
|
38
40
|
trackpoint.distance = dis != "" ? dis.to_f : nil
|
|
39
41
|
|
|
40
42
|
(t/:Position).each do |p|
|
|
41
|
-
trackpoint.lat = (p/:LatitudeDegrees).innerHTML
|
|
42
|
-
trackpoint.lng = (p/:LongitudeDegrees).innerHTML
|
|
43
|
+
trackpoint.lat = (p/:LatitudeDegrees).innerHTML.to_f
|
|
44
|
+
trackpoint.lng = (p/:LongitudeDegrees).innerHTML.to_f
|
|
43
45
|
end
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
if trackpoint.distance.nil? && !trackpoint.lat.nil?
|
|
48
|
+
totaldistance += trackpoint.calc_distance(trackpoints.last, trackpoint)
|
|
49
|
+
trackpoint.distance = totaldistance
|
|
50
|
+
end
|
|
51
|
+
trackpoint.speed = trackpoint.calc_speed(trackpoints.last, trackpoint)
|
|
52
|
+
|
|
53
|
+
trackpoints << trackpoint
|
|
46
54
|
|
|
47
55
|
|
|
48
56
|
## CALCULATE SPEED. ICK.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
# if distance_one.nil?
|
|
58
|
+
# distance_one = trackpoint.distance
|
|
59
|
+
# time_one = trackpoint.time
|
|
60
|
+
# else
|
|
61
|
+
# distance_two = trackpoint.distance
|
|
62
|
+
# next if distance_two.nil?
|
|
63
|
+
# time_two = trackpoint.time
|
|
64
|
+
# time_delta = time_two - time_one
|
|
65
|
+
# distance_delta = distance_two - distance_one
|
|
66
|
+
# if (distance_delta > 0 && time_delta > 0)
|
|
67
|
+
# trackpoint.speed = distance_delta / time_delta
|
|
68
|
+
# distance_one = distance_two
|
|
69
|
+
# time_one = time_two
|
|
70
|
+
# else
|
|
71
|
+
# trackpoint.speed = nil
|
|
72
|
+
# end
|
|
73
|
+
# end
|
|
66
74
|
end
|
|
67
75
|
|
|
68
76
|
if found
|
data/lib/hrmparser/trackpoint.rb
CHANGED
|
@@ -17,7 +17,7 @@ module HRMParser
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def calc_distance(pointA, pointB)
|
|
20
|
-
return 0 if pointA.nil? || pointA.lat.nil?
|
|
20
|
+
return 0 if pointA.nil? || pointA.lat.nil? || pointB.nil? || pointB.lat.nil?
|
|
21
21
|
|
|
22
22
|
dlng = pointB.lng - pointA.lng
|
|
23
23
|
dlat = pointB.lat - pointA.lat
|
|
@@ -38,8 +38,9 @@ module HRMParser
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def calc_speed(pointA, pointB)
|
|
41
|
-
return
|
|
41
|
+
return nil if pointA.nil? || pointA.lat.nil? || pointB.nil? || pointB.lat.nil?
|
|
42
42
|
time_delta = pointB.time - pointA.time
|
|
43
|
+
return nil if time_delta == 0
|
|
43
44
|
distance_delta = pointB.distance - pointA.distance
|
|
44
45
|
return distance_delta / time_delta
|
|
45
46
|
end
|
data/spec/hrmparser_spec.rb
CHANGED
|
@@ -36,7 +36,7 @@ module HRMParser
|
|
|
36
36
|
workout.average_hr.should == nil
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
context "Identifies files" do
|
|
41
41
|
it "identify file as garmin" do
|
|
42
42
|
type = Importer.file_type("spec/samples/small-garmin.TCX")
|
|
@@ -59,7 +59,7 @@ module HRMParser
|
|
|
59
59
|
importer = Importer::GPX.new(:data => data)
|
|
60
60
|
workout = importer.restore
|
|
61
61
|
workout.time.should == Time.parse("Thu May 07 21:32:31 UTC 2009")
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
# Duration is actualy less, but we don't account for stopped time right now
|
|
64
64
|
workout.duration.should be_close(6382,1)
|
|
65
65
|
end
|
|
@@ -108,6 +108,16 @@ module HRMParser
|
|
|
108
108
|
workout.altitude_gain.should be_nil
|
|
109
109
|
workout.trackpoints.should == {}
|
|
110
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
|
|
111
121
|
|
|
112
122
|
# Parsing the full XML is just slow. Commenting out for now.
|
|
113
123
|
it "gets workout level settings for outdoor workout" do
|
|
@@ -133,84 +143,82 @@ module HRMParser
|
|
|
133
143
|
end
|
|
134
144
|
|
|
135
145
|
it "doesn't have any 0 in latitude" do
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
|
151
161
|
end
|
|
152
162
|
|
|
153
163
|
context "Parse polar RS400 file" do
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
context "Parse a Polar RR file" do
|
|
172
|
-
it "calculates the heart rate from RR" do
|
|
173
|
-
filename ="spec/samples/polarRS800-RR.hrm"
|
|
174
|
-
data = File.read(filename)
|
|
175
|
-
importer = Importer::Polar.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
176
|
-
workout = importer.restore
|
|
177
|
-
workout.trackpoints.each {|tp| tp.hr.should < 220 && tp.hr.should > 30}
|
|
178
|
-
workout.average_hr.should be_close(115, 1)
|
|
179
|
-
workout.average_speed.should == nil
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
context "Parse a Suunto T6C RR file" do
|
|
184
|
-
it "finds the duration and time" do
|
|
185
|
-
filename = "spec/samples/suunto-t6-RR-stops.sdf"
|
|
186
|
-
data = File.read(filename)
|
|
187
|
-
importer = Importer::Suunto.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
188
|
-
workout = importer.restore
|
|
189
|
-
workout.duration.should be_close(4781,1)
|
|
190
|
-
workout.time.should == Time.parse("Thu May 07 14:16:07 -0700 2009")
|
|
164
|
+
it "finds the duration and time" do
|
|
165
|
+
filename ="spec/samples/polarRS400.hrm"
|
|
166
|
+
data = File.read(filename)
|
|
167
|
+
importer = Importer::Polar.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
168
|
+
workout = importer.restore
|
|
169
|
+
workout.duration.should be_close(3569,1)
|
|
170
|
+
workout.time.should == Time.parse("Thu Apr 16 12:01:55 -0700 2009")
|
|
171
|
+
end
|
|
172
|
+
it "calculates the average heartrate" do
|
|
173
|
+
filename ="spec/samples/polarRS400.hrm"
|
|
174
|
+
data = File.read(filename)
|
|
175
|
+
importer = Importer::Polar.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
176
|
+
workout = importer.restore
|
|
177
|
+
workout.average_hr.should be_close(145, 1)
|
|
178
|
+
end
|
|
191
179
|
end
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
180
|
+
|
|
181
|
+
context "Parse a Polar RR file" do
|
|
182
|
+
it "calculates the heart rate from RR" do
|
|
183
|
+
filename ="spec/samples/polarRS800-RR.hrm"
|
|
184
|
+
data = File.read(filename)
|
|
185
|
+
importer = Importer::Polar.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
186
|
+
workout = importer.restore
|
|
187
|
+
workout.trackpoints.each {|tp| tp.hr.should < 220 && tp.hr.should > 30}
|
|
188
|
+
workout.average_hr.should be_close(115, 1)
|
|
189
|
+
workout.average_speed.should == nil
|
|
190
|
+
end
|
|
201
191
|
end
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
192
|
+
|
|
193
|
+
context "Parse a Suunto T6C RR file" do
|
|
194
|
+
it "finds the duration and time" do
|
|
195
|
+
filename = "spec/samples/suunto-t6-RR-stops.sdf"
|
|
196
|
+
data = File.read(filename)
|
|
197
|
+
importer = Importer::Suunto.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
198
|
+
workout = importer.restore
|
|
199
|
+
workout.duration.should be_close(4781,1)
|
|
200
|
+
workout.time.should == Time.parse("Thu May 07 14:16:07 -0700 2009")
|
|
201
|
+
end
|
|
202
|
+
it "calculates the average HR & altitude" do
|
|
203
|
+
filename = "spec/samples/suunto-t6-RR-stops.sdf"
|
|
204
|
+
data = File.read(filename)
|
|
205
|
+
importer = Importer::Suunto.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
206
|
+
workout = importer.restore
|
|
207
|
+
workout.average_hr.should be_close(152,1)
|
|
208
|
+
workout.average_speed.should == nil
|
|
209
|
+
workout.trackpoints.each { |tp| tp.speed.should == nil }
|
|
210
|
+
workout.altitude_gain.should be_close(115, 10)
|
|
211
|
+
end
|
|
212
|
+
it "calculates the speed and distance" do
|
|
213
|
+
filename = "spec/samples/suunto-with-cadence-speed-distance.sdf"
|
|
214
|
+
data = File.read(filename)
|
|
215
|
+
importer = Importer::Suunto.new(:data => data, :time_zone => "Pacific Time (US & Canada)")
|
|
216
|
+
workout = importer.restore
|
|
217
|
+
workout.average_hr.should be_close(131,1)
|
|
218
|
+
workout.average_speed.should be_close(9.3, 0.1)
|
|
219
|
+
workout.altitude_gain.should be_close(75, 15)
|
|
220
|
+
workout.distance.should == 124597
|
|
221
|
+
end
|
|
211
222
|
end
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
end
|
|
215
223
|
end
|
|
216
224
|
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.
|
|
4
|
+
version: 0.4.9
|
|
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-06-10 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|