diff options
author | Chris Schlaeger <chris@linux.com> | 2018-03-18 21:04:06 +0100 |
---|---|---|
committer | Chris Schlaeger <chris@linux.com> | 2018-03-18 21:04:06 +0100 |
commit | b24b1a73baa7ef706a259ffcab926332e8e69387 (patch) | |
tree | 4b3708718b7fddd0c4dd96e7fbced0d9af1cf55b /lib | |
parent | 7caf6e842fd61975d3f402b1725ed0c9d9472c6c (diff) | |
download | postrunner-b24b1a73baa7ef706a259ffcab926332e8e69387.zip |
New: Add peak EPOC and elapsed time to activity summary
Diffstat (limited to 'lib')
-rw-r--r-- | lib/postrunner/ActivitySummary.rb | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/lib/postrunner/ActivitySummary.rb b/lib/postrunner/ActivitySummary.rb index f753ce9..3d7277c 100644 --- a/lib/postrunner/ActivitySummary.rb +++ b/lib/postrunner/ActivitySummary.rb @@ -87,6 +87,7 @@ module PostRunner { :metric => 'km', :statute => 'mi'}) ]) end t.row([ 'Time:', secsToHMS(session.total_timer_time) ]) + t.row([ 'Elapsed Time:', secsToHMS(session.total_elapsed_time) ]) t.row([ 'Avg. Speed:', local_value(session, 'avg_speed', '%.1f %s', { :metric => 'km/h', :statute => 'mph' }) ]) @@ -145,8 +146,12 @@ module PostRunner t.row([ 'Aerobic Training Effect:', session.total_training_effect ]) end + if (p_epoc = peak_epoc) > 0.0 + t.row([ 'Peak EPOC:', "%.0f ml/kg" % p_epoc ]) + end + if (trimp = trimp_exp) > 0.0 - t.row([ 'TRIMP (Exp):', trimp ]) + t.row([ 'TRIMP:', trimp.round ]) end rec_info = @fit_activity.recovery_info @@ -366,7 +371,7 @@ module PostRunner end def trimp_exp - # According to http://fellrnr.com/wiki/TRIMP + # According to Bannister/Morton # TRIMPexp = sum(D x HRr x 0.64e^y) # Where # @@ -374,8 +379,10 @@ module PostRunner # HRr is the Heart Rate as a fraction of Heart Rate Reserve # y is the HRr multiplied by 1.92 for men and 1.67 for women. return 0.0 unless (user_data = @fit_activity.user_data.first) + user_profile = @fit_activity.user_profiles.first hr_zones = @fit_activity.heart_rate_zones.first + session = @fit_activity.sessions[0] unless (user_profile && (rest_hr = user_profile.resting_heart_rate)) || (hr_zones && (rest_hr = hr_zones.resting_heart_rate)) @@ -387,22 +394,63 @@ module PostRunner # We must have a valid maximum heart rate to compute TRIMP. return 0.0 end + unless (session && session.avg_heart_rate && + avg_hr = session.avg_heart_rate) + return 0.0 + end - prev_timestamp = nil + sex_factor = user_data.gender == 'male' ? 1.92 : 1.67 + + # Instead of using the average heart rate for the whole activity we + # apply the equation for each heart rate sample and accumulate them. sum = 0.0 + prev_timestamp = nil @activity.fit_activity.records.each do |r| - if prev_timestamp && r.timestamp && r.heart_rate + # We need a valid timestmap and a valid previous timestamp. If they + # are more than 5 seconds appart we discard the values as there was + # likely a pause in the activity. + if prev_timestamp && r.timestamp && r.heart_rate && + r.timestamp - prev_timestamp <= 5 + # Compute the heart rate as fraction of the heart rate reserve hr_r = (r.heart_rate - rest_hr).to_f / (max_hr - rest_hr) - y = user_data.gender == :male ? 1.92 : 1.67 * hr_r - factor = 0.64 * Math.exp(y) - sum += ((r.timestamp - prev_timestamp) / 60.0) * hr_r * factor + + duration_min = (r.timestamp - prev_timestamp) / 60.0 + #sum += duration_min * hr_r * 0.64 * Math.exp(sex_factor * hr_r) + sum += duration_min * hr_r * 0.64 * Math.exp(sex_factor * hr_r) end + prev_timestamp = r.timestamp end - # There are so many fudge factors in the formula that we don't want to - # suggest more precision than there really is. - sum.round + sum + + # Alternatively here is an avarage HR based implementation + # hr_r = (session.avg_heart_rate - rest_hr).to_f / (max_hr - rest_hr) + # duration_min = session.total_elapsed_time / 60.0 + # duration_min * hr_r * 0.64 * Math.exp(sex_factor * hr_r) + end + + def peak_epoc + # Peak EPOC value according to figure 2 in the following white paper by + # FristBeat: + # https://www.firstbeat.com/wp-content/uploads/2015/10/white_paper_training_effect.pdf + unless @fit_activity.physiological_metrics && + (pm = @fit_activity.physiological_metrics.last) && + (te = pm.aerobic_training_effect) + return 0.0 + end + unless (user_data = @fit_activity.user_data.first) && + (ac = user_data.activity_class) + return 0.0 + end + + # The following formula was taken from + # http://www.movescount.com/apps/app10020404-EPOC_from_TE + # It apparently approximates the graph in figure 2 in the FirstBeat + # paper. + epoc = -11.0 + te * (20.0 + te * (-47.0/4.0 + te * (3.0 - te / 4.0))) + (-102.0 + te * (759.0 / 4.0 + te * (-2867.0 / 24.0 + + te * (139.0 / 4.0 - 73.0 / 24.0 * te))) - epoc) / 10.0 * ac + epoc end end |