postrunner 0.7.5 → 0.8.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.
- 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:
|