teich-hrmparser 0.4.4 → 0.4.5
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/lib/hrmparser/arraymath.rb +15 -15
- data/lib/hrmparser/importer/garmin.rb +83 -83
- data/lib/hrmparser/importer/gpx.rb +8 -8
- data/lib/hrmparser/importer/polar.rb +101 -101
- data/lib/hrmparser/importer/suunto.rb +45 -44
- data/lib/hrmparser/trackpoint.rb +8 -7
- data/lib/hrmparser/workout.rb +55 -53
- metadata +2 -2
data/CHANGELOG.txt
CHANGED
data/VERSION.yml
CHANGED
data/lib/hrmparser/arraymath.rb
CHANGED
|
@@ -3,23 +3,23 @@ require 'enumerator'
|
|
|
3
3
|
# Set of basic array math functions.
|
|
4
4
|
module ArrayMath
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
def aaverage
|
|
7
|
+
accum = self.asum
|
|
8
|
+
return nil if accum.nil? || self.size == 0
|
|
9
|
+
accum.to_f / self.size
|
|
10
|
+
end
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
def asum
|
|
13
|
+
self.map {|i| return nil if i.is_a?(String)}
|
|
14
|
+
inject(0){ |sum,item| sum + item }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
## Retun array FACTOR smaller. Average values to get smaller
|
|
18
|
+
def smoothed(factor)
|
|
19
|
+
self.enum_for(:each_slice, factor).map { |snipit| snipit.compact.aaverage }
|
|
20
|
+
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
class Array
|
|
24
|
-
|
|
24
|
+
include ArrayMath
|
|
25
25
|
end
|
|
@@ -1,85 +1,85 @@
|
|
|
1
1
|
module Importer
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
2
|
+
class Garmin
|
|
3
|
+
def initialize(opts = {:data => nil})
|
|
4
|
+
@data = opts[:data]
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def restore
|
|
8
|
+
workout = HRMParser::Workout.new(:duration => 0)
|
|
9
|
+
#data = Importer.read_in_file(@file_name)
|
|
10
|
+
|
|
11
|
+
@xml = Hpricot::XML(@data)
|
|
12
|
+
workout.time = Time.parse((@xml/:Id).innerHTML)
|
|
13
|
+
|
|
14
|
+
(@xml/:Lap).each do |lap|
|
|
15
|
+
f_time = (lap/:TotalTimeSeconds).innerHTML
|
|
16
|
+
workout.duration += Float f_time
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
found = false
|
|
20
|
+
trackpoints = Array.new
|
|
21
|
+
distance_one = nil
|
|
22
|
+
time_one = nil
|
|
23
|
+
|
|
24
|
+
(@xml/:Trackpoint).each do |t|
|
|
25
|
+
found = true
|
|
26
|
+
trackpoint = HRMParser::TrackPoint.new
|
|
27
|
+
|
|
28
|
+
trackpoint.time = Time.parse((t/:Time).innerHTML)
|
|
29
|
+
|
|
30
|
+
hr = (t/:HeartRateBpm/:Value).innerHTML
|
|
31
|
+
alt = (t/:AltitudeMeters).innerHTML
|
|
32
|
+
dis = (t/:DistanceMeters).innerHTML
|
|
33
|
+
|
|
34
|
+
trackpoint.hr = hr != "" ? hr.to_i : nil
|
|
35
|
+
trackpoint.altitude = alt != "" ? alt.to_f : nil
|
|
36
|
+
trackpoint.distance = dis != "" ? dis.to_f : nil
|
|
37
|
+
|
|
38
|
+
(t/:Position).each do |p|
|
|
39
|
+
trackpoint.lat = (p/:LatitudeDegrees).innerHTML
|
|
40
|
+
trackpoint.lng = (p/:LongitudeDegrees).innerHTML
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
trackpoints << trackpoint
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## CALCULATE SPEED. ICK.
|
|
47
|
+
if distance_one.nil?
|
|
48
|
+
distance_one = trackpoint.distance
|
|
49
|
+
time_one = trackpoint.time
|
|
50
|
+
else
|
|
51
|
+
distance_two = trackpoint.distance
|
|
52
|
+
next if distance_two.nil?
|
|
53
|
+
time_two = trackpoint.time
|
|
54
|
+
time_delta = time_two - time_one
|
|
55
|
+
distance_delta = distance_two - distance_one
|
|
56
|
+
if (distance_delta > 0 && time_delta > 0)
|
|
57
|
+
trackpoint.speed = distance_delta / time_delta
|
|
58
|
+
distance_one = distance_two
|
|
59
|
+
time_one = time_two
|
|
60
|
+
else
|
|
61
|
+
trackpoint.speed = nil
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if found
|
|
67
|
+
workout.trackpoints = trackpoints
|
|
68
|
+
workout.calc_average_speed!
|
|
69
|
+
workout.calc_altitude_gain!
|
|
70
|
+
workout.calc_average_hr!
|
|
71
|
+
trackpoints.reverse_each do |tp|
|
|
72
|
+
if !tp.distance.nil?
|
|
73
|
+
workout.distance = tp.distance
|
|
74
|
+
break
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
# workout.distance = trackpoints.last.distance if !trackpoints.last.nil? && !trackpoints.last.distance.nil?
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
return workout
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
85
|
end
|
|
@@ -7,7 +7,7 @@ module Importer
|
|
|
7
7
|
def restore
|
|
8
8
|
workout = HRMParser::Workout.new(:duration => 0)
|
|
9
9
|
@xml = Hpricot::XML(@data)
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
# Set the time based on first trackpoint. Seen an instance where the gpx begining time is wrong
|
|
12
12
|
ttime = (@xml/:trk/:trkpt/:time).first.innerHTML
|
|
13
13
|
workout.time = Time.parse(ttime)
|
|
@@ -16,26 +16,26 @@ module Importer
|
|
|
16
16
|
distance = 0
|
|
17
17
|
(@xml/:trk).each do |trk|
|
|
18
18
|
(trk/:trkpt).each do |trkpt|
|
|
19
|
-
|
|
19
|
+
trackpoint = HRMParser::TrackPoint.new
|
|
20
20
|
trackpoint.altitude = (trkpt/:ele).innerHTML.to_f
|
|
21
21
|
trackpoint.time = Time.parse((trkpt/:time).innerHTML)
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
trackpoint.lat = (trkpt.attributes)["lat"].to_f
|
|
24
24
|
trackpoint.lng = (trkpt.attributes)["lon"].to_f
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
distance += trackpoint.calc_distance(trackpoints.last, trackpoint)
|
|
27
27
|
trackpoint.distance = distance
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
trackpoint.speed = trackpoint.calc_speed(trackpoints.last, trackpoint)
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
trackpoints << trackpoint
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
workout.duration = trackpoints.last.time - trackpoints.first.time
|
|
36
36
|
workout.trackpoints = trackpoints
|
|
37
37
|
workout.calc_average_speed!
|
|
38
|
-
|
|
38
|
+
workout.calc_altitude_gain!
|
|
39
39
|
workout.distance = trackpoints.last.distance
|
|
40
40
|
return workout
|
|
41
41
|
end
|
|
@@ -1,103 +1,103 @@
|
|
|
1
1
|
module Importer
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
2
|
+
class Polar
|
|
3
|
+
|
|
4
|
+
attr_reader :time_zone
|
|
5
|
+
|
|
6
|
+
def initialize(opts = {:data => nil, :time_zone => "UTC"})
|
|
7
|
+
@data = opts[:data]
|
|
8
|
+
@time_zone = opts[:time_zone]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def restore
|
|
12
|
+
workout = HRMParser::Workout.new(:duration => 0)
|
|
13
|
+
|
|
14
|
+
params = parse_params
|
|
15
|
+
|
|
16
|
+
date = params["Date"] + " " + params["StartTime"] + " " + @time_zone
|
|
17
|
+
|
|
18
|
+
length_array = params["Length"].split(/:/)
|
|
19
|
+
workout.duration = (length_array[0].to_f * 3600) + (length_array[1].to_f * 60) + (length_array[2].to_f)
|
|
20
|
+
workout.time = Time.parse(date)
|
|
21
|
+
|
|
22
|
+
workout.trackpoints = get_trackpoints(workout.time, params["Interval"].to_i)
|
|
23
|
+
|
|
24
|
+
workout.calc_average_hr!
|
|
25
|
+
|
|
26
|
+
return workout
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
# def parse_tabbed_blocks
|
|
34
|
+
# # This is the list of tabbed blocks
|
|
35
|
+
# tabbed_blocks = %w[IntTimes ExtraData Sumary-123 Summary-TH]
|
|
36
|
+
# tabbed_blocks.each do |block_name|
|
|
37
|
+
# @polarHash[block_name] = []
|
|
38
|
+
# block_text = find_block(block_name)
|
|
39
|
+
# block_text.each do |block_line|
|
|
40
|
+
# @polarHash[block_name] << block_line.split(/\t/)
|
|
41
|
+
# end
|
|
42
|
+
# end
|
|
43
|
+
# end
|
|
44
|
+
|
|
45
|
+
# Params is the only "ini" style block
|
|
46
|
+
def parse_params
|
|
47
|
+
hash = {}
|
|
48
|
+
param_block = find_block("Params")
|
|
49
|
+
param_block.each do |param|
|
|
50
|
+
# /=/ in case that doesn't work
|
|
51
|
+
key, value = param.split("=", 2)
|
|
52
|
+
key = key.strip unless key.nil?
|
|
53
|
+
value = value.strip unless value.nil?
|
|
54
|
+
hash[key] = value unless key.nil?
|
|
55
|
+
end
|
|
56
|
+
return hash
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Polar file has [Foo] blocks. Return the data in the block
|
|
60
|
+
def find_block(header)
|
|
61
|
+
found = false
|
|
62
|
+
block = []
|
|
63
|
+
@data.each do |line|
|
|
64
|
+
line.chomp!
|
|
65
|
+
found = false if line =~ /^\[.*\]$/
|
|
66
|
+
block << line if found
|
|
67
|
+
found = true if line =~ /\[#{header}\]/
|
|
68
|
+
end
|
|
69
|
+
return block
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def parse_hrdata
|
|
73
|
+
hrdata = []
|
|
74
|
+
block_text = find_block("HRData")
|
|
75
|
+
block_text.each do |block_line|
|
|
76
|
+
hrdata << block_line.chomp
|
|
77
|
+
end
|
|
78
|
+
return hrdata
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def get_trackpoints(start_time, interval)
|
|
82
|
+
trackpoints = []
|
|
83
|
+
rrcounter = 0
|
|
84
|
+
|
|
85
|
+
hrdata = parse_hrdata
|
|
86
|
+
hrdata.each do |hrd|
|
|
87
|
+
tp = HRMParser::TrackPoint.new
|
|
88
|
+
|
|
89
|
+
if (interval == 238)
|
|
90
|
+
rrcounter += hrd.to_i
|
|
91
|
+
tp.hr = 60000 / hrd.to_i
|
|
92
|
+
tp.time = start_time + (rrcounter/1000)
|
|
93
|
+
else
|
|
94
|
+
tp.hr = hrd.to_i
|
|
95
|
+
tp.time = start_time + (interval * trackpoints.size)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
trackpoints << tp
|
|
99
|
+
end
|
|
100
|
+
return trackpoints
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
103
|
end
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
module Importer
|
|
2
2
|
class Suunto
|
|
3
3
|
attr_reader :time_zone
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
|
|
5
|
+
def initialize(opts = {:data => nil, :time_zone => "UTC"})
|
|
6
|
+
@data = opts[:data]
|
|
7
|
+
@time_zone = opts[:time_zone]
|
|
8
8
|
end
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
def restore
|
|
11
11
|
workout = HRMParser::Workout.new(:duration => 0)
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
params = parse_params("HEADER")
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
# Using DateTime because 1.8 at leas doesn't have a Time.strptime
|
|
16
16
|
# And european ordeirng consfuses time.parse
|
|
17
17
|
# TODO: must be some better way
|
|
@@ -20,17 +20,18 @@ module Importer
|
|
|
20
20
|
|
|
21
21
|
workout.time = Time.parse(time_for_parse)
|
|
22
22
|
workout.duration = params["DURATION"].to_f
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
workout.trackpoints = get_trackpoints
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
workout.calc_average_hr!
|
|
27
27
|
workout.calc_altitude_gain!
|
|
28
|
-
|
|
28
|
+
workout.calc_average_speed!
|
|
29
|
+
|
|
29
30
|
return workout
|
|
30
31
|
end
|
|
31
|
-
|
|
32
|
+
|
|
32
33
|
private
|
|
33
|
-
|
|
34
|
+
|
|
34
35
|
def parse_params(string)
|
|
35
36
|
hash = {}
|
|
36
37
|
param_block = find_block(string)
|
|
@@ -43,47 +44,47 @@ module Importer
|
|
|
43
44
|
end
|
|
44
45
|
return hash
|
|
45
46
|
end
|
|
46
|
-
|
|
47
|
+
|
|
47
48
|
def find_block(header)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
49
|
+
found = false
|
|
50
|
+
block = []
|
|
51
|
+
@data.each do |line|
|
|
52
|
+
line.chomp!
|
|
53
|
+
found = false if line =~ /^\[.*\]$/
|
|
54
|
+
block << line if found
|
|
55
|
+
found = true if line =~ /\[#{header}\]/
|
|
56
|
+
end
|
|
57
|
+
return block
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def parse_data(string)
|
|
61
|
+
data = []
|
|
62
|
+
block_text = find_block(string)
|
|
63
|
+
block_text.each do |block_line|
|
|
64
|
+
data << block_line.chomp
|
|
65
|
+
end
|
|
66
|
+
return data
|
|
67
|
+
end
|
|
68
|
+
|
|
68
69
|
def get_trackpoints
|
|
69
70
|
trackpoints = []
|
|
70
|
-
|
|
71
|
+
logs = parse_data("POINTS")
|
|
71
72
|
for line in logs do
|
|
72
|
-
type, date, time, altitude, blank, blank, hr, epoc, respiration, ventilation, vo2, kcal, blank, blank,
|
|
73
|
+
type, date, time, altitude, blank, blank, hr, epoc, respiration, ventilation, vo2, kcal, blank, blank, distance, speed, cadence, temp = line.split(/,/)
|
|
73
74
|
next if type == "\"T6LAP\""
|
|
74
|
-
|
|
75
|
+
|
|
75
76
|
trackpoint = HRMParser::TrackPoint.new
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
|
|
78
|
+
points_f = %w[epoc kcal speed]
|
|
79
|
+
points_i = %w[altitude hr respiration ventilation vo2 distance cadence temp]
|
|
80
|
+
|
|
81
|
+
points_f.each { |p| trackpoint.send("#{p}=".to_sym, (eval p).to_f) }
|
|
82
|
+
points_i.each { |p| trackpoint.send("#{p}=".to_sym, (eval p).to_i) }
|
|
78
83
|
|
|
79
84
|
dt = DateTime.strptime(date + " " + time, "%d.%m.%Y %H:%M.%S")
|
|
80
85
|
time_for_parse = dt.strftime("%b %d %H:%M:%S @time_zone %Y")
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
trackpoint.temp = temp.to_i
|
|
84
|
-
trackpoint.kcal = kcal.to_i
|
|
85
|
-
trackpoint.altitude = altitude.to_i
|
|
86
|
-
|
|
86
|
+
trackpoint.time = Time.parse(time_for_parse)
|
|
87
|
+
|
|
87
88
|
trackpoints << trackpoint
|
|
88
89
|
end
|
|
89
90
|
return trackpoints
|
data/lib/hrmparser/trackpoint.rb
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
module HRMParser
|
|
2
2
|
class TrackPoint
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
RAD_PER_DEG = 0.017453293 # PI/180
|
|
5
|
-
|
|
6
|
-
attr_accessor :lat, :lng, :altitude, :speed, :hr, :distance, :time, :cadence, :temp, :kcal
|
|
5
|
+
|
|
6
|
+
attr_accessor :lat, :lng, :altitude, :speed, :hr, :distance, :time, :cadence, :temp, :kcal, :epoc, :respiration, :ventilation, :vo2, :cadence
|
|
7
|
+
|
|
7
8
|
def initialize(opts = {:lat => nil, :lng => nil, :altitude => nil, :speed => nil, :hr => nil, :distance => nil, :cadence => nil, :time => Time.now})
|
|
8
9
|
@lat = opts[:lat]
|
|
9
10
|
@lng = opts[:lng]
|
|
@@ -17,7 +18,7 @@ module HRMParser
|
|
|
17
18
|
|
|
18
19
|
def calc_distance(pointA, pointB)
|
|
19
20
|
return 0 if pointA.nil? || pointA.lat.nil?
|
|
20
|
-
|
|
21
|
+
|
|
21
22
|
dlng = pointB.lng - pointA.lng
|
|
22
23
|
dlat = pointB.lat - pointA.lat
|
|
23
24
|
|
|
@@ -29,13 +30,13 @@ module HRMParser
|
|
|
29
30
|
|
|
30
31
|
lat2_rad = pointB.lat * RAD_PER_DEG
|
|
31
32
|
lng2_rad = pointB.lng * RAD_PER_DEG
|
|
32
|
-
|
|
33
|
+
|
|
33
34
|
a = (Math.sin(dlat_rad/2))**2 + Math.cos(lat1_rad) * Math.cos(lat2_rad) * (Math.sin(dlng_rad/2))**2
|
|
34
35
|
c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a))
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
return 6371000 * c
|
|
37
38
|
end
|
|
38
|
-
|
|
39
|
+
|
|
39
40
|
def calc_speed(pointA, pointB)
|
|
40
41
|
return 0 if pointA.nil? || pointA.lat.nil?
|
|
41
42
|
time_delta = pointB.time - pointA.time
|
data/lib/hrmparser/workout.rb
CHANGED
|
@@ -1,55 +1,57 @@
|
|
|
1
1
|
module HRMParser
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
2
|
+
class Workout
|
|
3
|
+
attr_accessor :duration, :distance, :time, :name, :file_name, :trackpoints
|
|
4
|
+
attr_reader :average_hr, :data, :average_speed, :altitude_gain
|
|
5
|
+
|
|
6
|
+
def initialize(opts = {:duration => nil, :distance => nil, :time => Time.now, :name => nil, :file_name => nil})
|
|
7
|
+
@duration = opts[:duration]
|
|
8
|
+
@name = opts[:name]
|
|
9
|
+
@time = opts[:time]
|
|
10
|
+
@distance = opts[:distance]
|
|
11
|
+
@file_name = opts[:file_name]
|
|
12
|
+
|
|
13
|
+
@data = nil
|
|
14
|
+
@trackpoints = {}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def calc_average_hr!
|
|
19
|
+
ahr = heart_rates.compact.aaverage
|
|
20
|
+
@average_hr = ahr == 0.0 ? nil : ahr
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def calc_average_speed!
|
|
24
|
+
aspeed = speeds.compact.aaverage
|
|
25
|
+
@average_speed = aspeed == 0.0 ? nil : aspeed
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def calc_altitude_gain!
|
|
29
|
+
gain = 0
|
|
30
|
+
smoothed_altitude = altitudes.smoothed(10)
|
|
31
|
+
start = smoothed_altitude.first
|
|
32
|
+
smoothed_altitude.each do |alt|
|
|
33
|
+
diff = alt - start
|
|
34
|
+
if (diff > 0)
|
|
35
|
+
gain += diff
|
|
36
|
+
end
|
|
37
|
+
start = alt
|
|
38
|
+
end
|
|
39
|
+
@altitude_gain = gain == 0.0 ? nil : gain
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
## Some helper functions that return specific files from trackpoint as array
|
|
45
|
+
def heart_rates
|
|
46
|
+
@trackpoints.map {|tp| tp.hr }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def speeds
|
|
50
|
+
@trackpoints.map {|tp| tp.speed }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def altitudes
|
|
54
|
+
@trackpoints.map { |tp| tp.altitude }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
55
57
|
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.5
|
|
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-05-
|
|
12
|
+
date: 2009-05-11 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|