Files
GoldenCheetah/src/AerobicDecoupling.cpp
Mark Liversedge 7bb9cf5462 Long Term Metrics
A user configurable chart for showing ride metrics and
other calculated values over time.

* Uses SQLITE database to store metrics
* Supports any metric available from the metric factory
* Adds new MaxHr, VI, Peak Power and Time In Zone metric
* Also includes LTS/STS/SB for PM charting
* Aggregates in days, weeks, months or years
* Reads and Updates seasons.xml
* Adds cycles and adhoc date ranges in seasons.xml
* Date ranges can be selected on the plot with shift-left click
* Allows users to customise preferences for color, symbols et al
* Allows user to customise metric names and unit names
* Supports smooth curves and topN highlighting
* Has a linear regress trend line function
* Allows users to save charts to charts.xml
* A default charts.xml is built-in
* A chart manager to import/export/rename/delete charts etc
* Provides a tooltip to provide basic datapoint information
* Performance Manager adjusted to use the MetricDB
* User configurable setting for SB calculation (today/tomorrow)
2010-02-25 08:01:43 -08:00

97 lines
3.6 KiB
C++

/*
* Copyright (c) 2009 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "RideMetric.h"
// This metric computes aerobic decoupling percentage as described
// by Joe Friel:
//
// http://www.trainingbible.com/pdf/AeT_Training.pdf
//
// Aerobic decoupling is a measure of how much heart rate rises or
// how much power falls off during the course of a long ride. Joe suggests
// that a rise of more than 5% in the heart rate to power ratio between the
// two halfs of a long ride indicates that the ride was performed above the
// aerobic threshold.
//
// How you actually compute these things over messy data isn't always
// straightforward. For this implementation, I cut the set of data points in
// half and compute the average power and heart rate over all the points in
// either half that have a non-zero heart rate. I then calculate the change
// in heart rate to power ratio as described by Friel.
class AerobicDecoupling : public RideMetric {
double percent;
public:
AerobicDecoupling() : percent(0.0) {}
QString symbol() const { return "aerobic_decoupling"; }
QString name() const { return QObject::tr("Aerobic Decoupling"); }
MetricType type() const { return RideMetric::Average; }
QString units(bool) const { return "%"; }
int precision() const { return 2; }
double conversion() const { return 1.0; }
double value(bool) const { return percent; }
void compute(const RideFile *ride, const Zones *, int,
const QHash<QString,RideMetric*> &) {
double firstHalfPower = 0.0, secondHalfPower = 0.0;
double firstHalfHR = 0.0, secondHalfHR = 0.0;
int halfway = ride->dataPoints().size() / 2;
int count = 0;
int firstHalfCount = 0;
int secondHalfCount = 0;
foreach(const RideFilePoint *point, ride->dataPoints()) {
if (count++ < halfway) {
if (point->hr > 0) {
firstHalfPower += point->watts;
firstHalfHR += point->hr;
++firstHalfCount;
}
}
else {
if (point->hr > 0) {
secondHalfPower += point->watts;
secondHalfHR += point->hr;
++secondHalfCount;
}
}
}
if ((firstHalfCount > 0) && (secondHalfCount > 0)) {
firstHalfPower /= firstHalfCount;
secondHalfPower /= secondHalfCount;
firstHalfHR /= firstHalfCount;
secondHalfHR /= secondHalfCount;
double firstHalfRatio = firstHalfHR / firstHalfPower;
double secondHalfRatio = secondHalfHR / secondHalfPower;
percent = 100.0 * (secondHalfRatio - firstHalfRatio) / firstHalfRatio;
}
}
RideMetric *clone() const { return new AerobicDecoupling(*this); }
};
static bool add() {
RideMetricFactory::instance().addMetric(AerobicDecoupling());
return true;
}
static bool added = add();