postrunner 0.7.5 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/postrunner/ActivitySummary.rb +162 -5
- data/lib/postrunner/ChartView.rb +7 -0
- data/lib/postrunner/HRZoneDetector.rb +77 -0
- data/lib/postrunner/Main.rb +3 -1
- data/lib/postrunner/PersonalRecords.rb +3 -0
- data/lib/postrunner/version.rb +2 -2
- data/postrunner.gemspec +11 -10
- data/spec/PostRunner_spec.rb +3 -1
- metadata +17 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e282bd17e22dd3984588ac737f95e0bb819ee674
|
4
|
+
data.tar.gz: bf6a551a65a477b2a68526c549488098e9374a00
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e35e8f9d8604cdf26d76d5686e70739f783e0fc385fa9b686e8abe7d5dcea84e4a0e93f06a8b1bd697d5add11539cbc0d9c8a20ac5b6ab74493c7c7eaa01853f
|
7
|
+
data.tar.gz: 8eb18c7a1af1c8d56889985d4bfa203ca4b2dd39fa7941220ee835613b06a2bdb986bab58fdd95c4b23fc2ee5e7c275e0b4c5d6461ad0fcb68b83815a6892b59
|
@@ -16,11 +16,16 @@ require 'postrunner/FlexiTable'
|
|
16
16
|
require 'postrunner/ViewFrame'
|
17
17
|
require 'postrunner/HRV_Analyzer'
|
18
18
|
require 'postrunner/Percentiles'
|
19
|
+
require 'postrunner/HRZoneDetector'
|
19
20
|
|
20
21
|
module PostRunner
|
21
22
|
|
22
23
|
class ActivitySummary
|
23
24
|
|
25
|
+
class HRZone < Struct.new(:index, :low, :high, :time_in_zone,
|
26
|
+
:percent_in_zone)
|
27
|
+
end
|
28
|
+
|
24
29
|
include Fit4Ruby::Converters
|
25
30
|
|
26
31
|
def initialize(activity, unit_system, custom_fields)
|
@@ -33,9 +38,12 @@ module PostRunner
|
|
33
38
|
end
|
34
39
|
|
35
40
|
def to_s
|
36
|
-
summary.to_s + "\n" +
|
37
|
-
|
38
|
-
|
41
|
+
s = summary.to_s + "\n" +
|
42
|
+
(@activity.note ? note.to_s + "\n" : '') +
|
43
|
+
laps.to_s
|
44
|
+
s += hr_zones.to_s if has_hr_zones?
|
45
|
+
|
46
|
+
s
|
39
47
|
end
|
40
48
|
|
41
49
|
def to_html(doc)
|
@@ -45,6 +53,10 @@ module PostRunner
|
|
45
53
|
ViewFrame.new('note', 'Note', width, note,
|
46
54
|
true).to_html(doc) if @activity.note
|
47
55
|
ViewFrame.new('laps', 'Laps', width, laps, true).to_html(doc)
|
56
|
+
if has_hr_zones?
|
57
|
+
ViewFrame.new('hr_zones', 'Heart Rate Zones', width, hr_zones, true).
|
58
|
+
to_html(doc)
|
59
|
+
end
|
48
60
|
end
|
49
61
|
|
50
62
|
private
|
@@ -119,8 +131,19 @@ module PostRunner
|
|
119
131
|
"#{(2 * session.avg_cadence).round} rpm" : '-' ])
|
120
132
|
end
|
121
133
|
|
122
|
-
|
123
|
-
|
134
|
+
if @fit_activity.physiological_metrics &&
|
135
|
+
(physiological_metrics = @fit_activity.physiological_metrics.last)
|
136
|
+
if physiological_metrics.anaerobic_training_effect
|
137
|
+
t.row([ 'Anaerobic Training Effect:',
|
138
|
+
physiological_metrics.anaerobic_training_effect ])
|
139
|
+
end
|
140
|
+
if physiological_metrics.aerobic_training_effect
|
141
|
+
t.row([ 'Aerobic Training Effect:',
|
142
|
+
physiological_metrics.aerobic_training_effect ])
|
143
|
+
end
|
144
|
+
elsif session.total_training_effect
|
145
|
+
t.row([ 'Aerobic Training Effect:', session.total_training_effect ])
|
146
|
+
end
|
124
147
|
|
125
148
|
rec_info = @fit_activity.recovery_info
|
126
149
|
t.row([ 'Ignored Recovery Time:',
|
@@ -178,6 +201,140 @@ module PostRunner
|
|
178
201
|
t
|
179
202
|
end
|
180
203
|
|
204
|
+
def hr_zones
|
205
|
+
session = @fit_activity.sessions[0]
|
206
|
+
|
207
|
+
t = FlexiTable.new
|
208
|
+
t.head
|
209
|
+
t.row([ 'Zone', 'Exertion', 'Min. HR [bpm]', 'Max. HR [bpm]',
|
210
|
+
'Time in Zone', '% of Time in Zone' ])
|
211
|
+
t.set_column_attributes([
|
212
|
+
{ :halign => :right },
|
213
|
+
{ :halign => :left},
|
214
|
+
{ :halign => :right },
|
215
|
+
{ :halign => :right },
|
216
|
+
{ :halign => :right },
|
217
|
+
{ :halign => :right },
|
218
|
+
])
|
219
|
+
t.body
|
220
|
+
|
221
|
+
# Calculate the total time in all the 5 relevant zones. We'll need this
|
222
|
+
# later as the basis for the percentage values.
|
223
|
+
total_secs = 0
|
224
|
+
zones = gather_hr_zones
|
225
|
+
|
226
|
+
zones.each do |zone|
|
227
|
+
t.cell(zone.index + 1)
|
228
|
+
t.cell([ 'Warm Up', 'Easy', 'Aerobic', 'Threshold', 'Maximum' ][zone.index])
|
229
|
+
t.cell(zone.low)
|
230
|
+
t.cell(zone.high)
|
231
|
+
t.cell(secsToHMS(zone.time_in_zone))
|
232
|
+
t.cell('%.0f%%' % zone.percent_in_zone)
|
233
|
+
|
234
|
+
t.new_row
|
235
|
+
end
|
236
|
+
|
237
|
+
t
|
238
|
+
end
|
239
|
+
|
240
|
+
def has_hr_zones?
|
241
|
+
# Depending on the age of the device we may have heart rate zone data
|
242
|
+
# with zone boundaries, without zone boundaries or no data at all.
|
243
|
+
if @fit_activity.heart_rate_zones.empty?
|
244
|
+
# The FIT file has no heart_rate_zone records. It might have a
|
245
|
+
# time_in_hr_zone record for the session.
|
246
|
+
counted_zones = 0
|
247
|
+
total_time_in_zone = 0
|
248
|
+
each_hr_zone_with_index do |secs_in_zone, i|
|
249
|
+
if secs_in_zone
|
250
|
+
counted_zones += 1
|
251
|
+
total_time_in_zone += secs_in_zone
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
return counted_zones == 5 && total_time_in_zone > 0.0
|
256
|
+
else
|
257
|
+
# The FIT file has explicit heart_rate_zones records. We need the
|
258
|
+
# session record that has type 19.
|
259
|
+
@fit_activity.heart_rate_zones.each do |hrz|
|
260
|
+
if hrz.type == 18 && hrz.heart_rate_zones &&
|
261
|
+
!hrz.heart_rate_zones.empty?
|
262
|
+
return true
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def gather_hr_zones
|
269
|
+
zones = []
|
270
|
+
|
271
|
+
if @fit_activity.heart_rate_zones.empty?
|
272
|
+
# The FIT file has no heart_rate_zone records. It might have a
|
273
|
+
# time_in_hr_zone record for the session.
|
274
|
+
counted_zones = 0
|
275
|
+
total_time_in_zone = 0
|
276
|
+
each_hr_zone_with_index do |secs_in_zone, i|
|
277
|
+
if secs_in_zone
|
278
|
+
counted_zones += 1
|
279
|
+
total_time_in_zone += secs_in_zone
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
if counted_zones == 5 && total_time_in_zone > 0.0
|
284
|
+
session = @fit_activity.sessions[0]
|
285
|
+
hr_mins = HRZoneDetector::detect_zones(
|
286
|
+
@fit_activity.records, session.time_in_hr_zone[0..5])
|
287
|
+
0.upto(4) do |i|
|
288
|
+
low = hr_mins[i + 1]
|
289
|
+
high = i == HRZoneDetector::GARMIN_ZONES - 1 ?
|
290
|
+
session.max_heart_rate || '-' :
|
291
|
+
hr_mins[i + 2].nil? || hr_mins[i + 2] == 0 ? '-' :
|
292
|
+
(hr_mins[i + 2] - 1)
|
293
|
+
tiz = @fit_activity.sessions[0].time_in_hr_zone[i + 1]
|
294
|
+
piz = tiz / total_time_in_zone * 100.0
|
295
|
+
zones << HRZone.new(i, low, high, tiz, piz)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
else
|
299
|
+
@fit_activity.heart_rate_zones.each do |zone|
|
300
|
+
if zone.type == 18
|
301
|
+
total_time = 0.0
|
302
|
+
if zone.time_in_hr_zone
|
303
|
+
zone.time_in_hr_zone.each { |tiz| total_time += tiz }
|
304
|
+
end
|
305
|
+
break if total_time <= 0.0
|
306
|
+
if zone.heart_rate_zones
|
307
|
+
zone.heart_rate_zones.each_with_index do |hr, i|
|
308
|
+
break if i > 4
|
309
|
+
zones << HRZone.new(i, hr, zone.heart_rate_zones[i + 1],
|
310
|
+
zone.time_in_hr_zone[i + 1],
|
311
|
+
zone.time_in_hr_zone[i + 1] /
|
312
|
+
total_time * 100.0)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
break
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
zones
|
321
|
+
end
|
322
|
+
|
323
|
+
def each_hr_zone_with_index
|
324
|
+
return unless (zones = @fit_activity.sessions[0].time_in_hr_zone)
|
325
|
+
|
326
|
+
zones.each_with_index do |secs_in_zone, i|
|
327
|
+
# There seems to be a zone 0 in the FIT files that isn't displayed on
|
328
|
+
# the watch or Garmin Connect. Just ignore it.
|
329
|
+
next if i == 0
|
330
|
+
# There are more zones in the FIT file, but they are not displayed on
|
331
|
+
# the watch or on the GC.
|
332
|
+
break if i >= 6
|
333
|
+
|
334
|
+
yield(secs_in_zone, i)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
181
338
|
def local_value(fdr, field, format, units)
|
182
339
|
unit = units[@unit_system]
|
183
340
|
value = fdr.get_as(field, unit)
|
data/lib/postrunner/ChartView.rb
CHANGED
@@ -75,6 +75,13 @@ module PostRunner
|
|
75
75
|
:colors => '#900000',
|
76
76
|
:show => false
|
77
77
|
},
|
78
|
+
{
|
79
|
+
:id => 'performance_condition',
|
80
|
+
:label => 'Performance Condition',
|
81
|
+
:graph => :line_graph,
|
82
|
+
:colors => '#7CB7E7',
|
83
|
+
:show => true
|
84
|
+
},
|
78
85
|
{
|
79
86
|
:id => 'run_cadence',
|
80
87
|
:label => 'Run Cadence',
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = HRZoneDetector.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2017 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
13
|
+
module PostRunner
|
14
|
+
|
15
|
+
module HRZoneDetector
|
16
|
+
|
17
|
+
# Number of heart rate zones supported by Garmin devices.
|
18
|
+
GARMIN_ZONES = 5
|
19
|
+
# Maximum heart rate that can be stored in FIT files.
|
20
|
+
MAX_HR = 255
|
21
|
+
|
22
|
+
def HRZoneDetector::detect_zones(fit_records, secs_in_zones)
|
23
|
+
if fit_records.empty?
|
24
|
+
raise RuntimeError, "records must not be empty"
|
25
|
+
end
|
26
|
+
if secs_in_zones.size != GARMIN_ZONES + 1
|
27
|
+
raise RuntimeError, "secs_in_zones must have #{GARMIN_ZONES + 1} " +
|
28
|
+
"elements"
|
29
|
+
end
|
30
|
+
|
31
|
+
# We generate a histogram of the time spent at each integer heart rate.
|
32
|
+
histogram = Array.new(MAX_HR + 1, 0)
|
33
|
+
|
34
|
+
last_timestamp = nil
|
35
|
+
fit_records.each do |record|
|
36
|
+
next unless record.heart_rate
|
37
|
+
|
38
|
+
if last_timestamp
|
39
|
+
# We ignore all intervals that are larger than 10 seconds. This
|
40
|
+
# potentially conflicts with smart recording, but I can't see how a
|
41
|
+
# larger sampling interval can yield usable results.
|
42
|
+
if (delta_t = record.timestamp - last_timestamp) <= 10
|
43
|
+
histogram[record.heart_rate] += delta_t
|
44
|
+
end
|
45
|
+
end
|
46
|
+
last_timestamp = record.timestamp
|
47
|
+
end
|
48
|
+
|
49
|
+
# We'll process zones 5 downto 1.
|
50
|
+
zone = GARMIN_ZONES
|
51
|
+
hr_mins = Array.new(GARMIN_ZONES)
|
52
|
+
# Sum of time spent in current zone.
|
53
|
+
secs_in_current_zone = 0
|
54
|
+
# We process the histogramm from highest to smallest HR value. Whenever
|
55
|
+
# we have accumulated the provided amount of time we have found a HR
|
56
|
+
# zone boundary. We complete the current zone and continue with the next
|
57
|
+
# one.
|
58
|
+
MAX_HR.downto(0) do |i|
|
59
|
+
secs_in_current_zone += histogram[i]
|
60
|
+
|
61
|
+
if secs_in_current_zone > secs_in_zones[zone]
|
62
|
+
# In case we have collected more time than was specified for the
|
63
|
+
# zone we carry the delta over to the next zone.
|
64
|
+
secs_in_current_zone -= secs_in_zones[zone]
|
65
|
+
# puts "Zone #{zone}: #{secs_in_current_zone} #{secs_in_zones[zone]}"
|
66
|
+
break if (zone -= 1) < 0
|
67
|
+
end
|
68
|
+
hr_mins[zone] = i
|
69
|
+
end
|
70
|
+
|
71
|
+
hr_mins
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
data/lib/postrunner/Main.rb
CHANGED
@@ -92,6 +92,8 @@ module PostRunner
|
|
92
92
|
"#{VERSION}!")
|
93
93
|
end
|
94
94
|
return -1
|
95
|
+
ensure
|
96
|
+
@db.exit if @db
|
95
97
|
end
|
96
98
|
end
|
97
99
|
|
@@ -103,7 +105,7 @@ module PostRunner
|
|
103
105
|
|
104
106
|
opts.separator <<"EOT"
|
105
107
|
|
106
|
-
Copyright (c) 2014, 2015, 2016 by Chris Schlaeger
|
108
|
+
Copyright (c) 2014, 2015, 2016, 2017 by Chris Schlaeger
|
107
109
|
|
108
110
|
This program is free software; you can redistribute it and/or modify it under
|
109
111
|
the terms of version 2 of the GNU General Public License as published by the
|
@@ -346,6 +346,9 @@ module PostRunner
|
|
346
346
|
# meters)
|
347
347
|
speed_records = {}
|
348
348
|
|
349
|
+
# Ignore FIT files that don't have an activity or session
|
350
|
+
return unless activity.fit_activity && activity.fit_activity.sessions
|
351
|
+
|
349
352
|
segment_start_time = activity.fit_activity.sessions[0].start_time
|
350
353
|
segment_start_distance = 0.0
|
351
354
|
|
data/lib/postrunner/version.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# = version.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
5
|
#
|
6
|
-
# Copyright (c) 2014, 2015, 2016 by Chris Schlaeger <cs@taskjuggler.org>
|
6
|
+
# Copyright (c) 2014, 2015, 2016, 2017 by Chris Schlaeger <cs@taskjuggler.org>
|
7
7
|
#
|
8
8
|
# This program is free software; you can redistribute it and/or modify
|
9
9
|
# it under the terms of version 2 of the GNU General Public License as
|
@@ -11,5 +11,5 @@
|
|
11
11
|
#
|
12
12
|
|
13
13
|
module PostRunner
|
14
|
-
VERSION = '0.
|
14
|
+
VERSION = '0.8.0'
|
15
15
|
end
|
data/postrunner.gemspec
CHANGED
@@ -10,14 +10,15 @@ GEM_SPEC = Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["cs@taskjuggler.org"]
|
11
11
|
spec.summary = %q{Application to manage and analyze Garmin FIT files.}
|
12
12
|
spec.description = %q{PostRunner is an application to manage FIT files
|
13
|
-
such as those produced by Garmin products like the Forerunner 620 (FR620)
|
14
|
-
Fenix 3
|
15
|
-
analyze the data. In addition to the common features like
|
16
|
-
rates, elevation and other captured values it also
|
17
|
-
variability (HRV) analysis. It can also update
|
18
|
-
(EPO) data on the device to speed-up GPS fix times.
|
19
|
-
to Garmin Connect. The software has been
|
20
|
-
should work on other operating systems as
|
13
|
+
such as those produced by Garmin products like the Forerunner 620 (FR620),
|
14
|
+
Fenix 3, Fenix 3HR, Fenix 5 (S and X). It allows you to import the files from
|
15
|
+
the device and analyze the data. In addition to the common features like
|
16
|
+
plotting pace, heart rates, elevation and other captured values it also
|
17
|
+
provides a heart rate variability (HRV) and sleep analysis. It can also update
|
18
|
+
satellite orbit prediction (EPO) data on the device to speed-up GPS fix times.
|
19
|
+
It is an offline alternative to Garmin Connect. The software has been
|
20
|
+
developed and tested on Linux but should work on other operating systems as
|
21
|
+
well.}
|
21
22
|
spec.homepage = 'https://github.com/scrapper/postrunner'
|
22
23
|
spec.license = "GNU GPL version 2"
|
23
24
|
|
@@ -27,8 +28,8 @@ should work on other operating systems as well.}
|
|
27
28
|
spec.require_paths = ["lib"]
|
28
29
|
spec.required_ruby_version = '>=2.0'
|
29
30
|
|
30
|
-
spec.add_dependency 'fit4ruby', '~> 1.
|
31
|
-
spec.add_dependency 'perobs', '~>
|
31
|
+
spec.add_dependency 'fit4ruby', '~> 1.6.0'
|
32
|
+
spec.add_dependency 'perobs', '~> 3.0.1'
|
32
33
|
spec.add_dependency 'nokogiri', '~> 1.6'
|
33
34
|
|
34
35
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
data/spec/PostRunner_spec.rb
CHANGED
@@ -31,7 +31,9 @@ describe PostRunner::Main do
|
|
31
31
|
$stderr = old_stderr
|
32
32
|
end
|
33
33
|
|
34
|
-
|
34
|
+
stdout.rewind
|
35
|
+
stderr.rewind
|
36
|
+
{ :retval => retval, :stdout => stdout.read, :stderr => stderr.read}
|
35
37
|
end
|
36
38
|
|
37
39
|
before(:all) do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: postrunner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Schlaeger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fit4ruby
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.6.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: 1.6.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: perobs
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 3.0.1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 3.0.1
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: nokogiri
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,14 +110,15 @@ dependencies:
|
|
110
110
|
version: 0.8.7
|
111
111
|
description: |-
|
112
112
|
PostRunner is an application to manage FIT files
|
113
|
-
such as those produced by Garmin products like the Forerunner 620 (FR620)
|
114
|
-
Fenix 3
|
115
|
-
analyze the data. In addition to the common features like
|
116
|
-
rates, elevation and other captured values it also
|
117
|
-
variability (HRV) analysis. It can also update
|
118
|
-
(EPO) data on the device to speed-up GPS fix times.
|
119
|
-
to Garmin Connect. The software has been
|
120
|
-
should work on other operating systems as
|
113
|
+
such as those produced by Garmin products like the Forerunner 620 (FR620),
|
114
|
+
Fenix 3, Fenix 3HR, Fenix 5 (S and X). It allows you to import the files from
|
115
|
+
the device and analyze the data. In addition to the common features like
|
116
|
+
plotting pace, heart rates, elevation and other captured values it also
|
117
|
+
provides a heart rate variability (HRV) and sleep analysis. It can also update
|
118
|
+
satellite orbit prediction (EPO) data on the device to speed-up GPS fix times.
|
119
|
+
It is an offline alternative to Garmin Connect. The software has been
|
120
|
+
developed and tested on Linux but should work on other operating systems as
|
121
|
+
well.
|
121
122
|
email:
|
122
123
|
- cs@taskjuggler.org
|
123
124
|
executables:
|
@@ -154,6 +155,7 @@ files:
|
|
154
155
|
- lib/postrunner/FitFileStore.rb
|
155
156
|
- lib/postrunner/FlexiTable.rb
|
156
157
|
- lib/postrunner/HRV_Analyzer.rb
|
158
|
+
- lib/postrunner/HRZoneDetector.rb
|
157
159
|
- lib/postrunner/HTMLBuilder.rb
|
158
160
|
- lib/postrunner/LinearPredictor.rb
|
159
161
|
- lib/postrunner/Log.rb
|
@@ -339,7 +341,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
339
341
|
version: '0'
|
340
342
|
requirements: []
|
341
343
|
rubyforge_project:
|
342
|
-
rubygems_version: 2.2.
|
344
|
+
rubygems_version: 2.2.5
|
343
345
|
signing_key:
|
344
346
|
specification_version: 4
|
345
347
|
summary: Application to manage and analyze Garmin FIT files.
|
@@ -351,4 +353,3 @@ test_files:
|
|
351
353
|
- spec/PostRunner_spec.rb
|
352
354
|
- spec/View_spec.rb
|
353
355
|
- spec/spec_helper.rb
|
354
|
-
has_rdoc:
|