mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Added Equivalent Performance for Target Race to VDOT Calculator
Also fixed constant term error in VO2 formula
This commit is contained in:
@@ -31,7 +31,7 @@ double
|
||||
VDOTCalculator::vdot(double mins, double vel)
|
||||
{
|
||||
// estimated VO2 cost of running at vel speed in m/min
|
||||
double VO2 = -4.3 + 0.182258*vel + 0.000104*pow(vel, 2);
|
||||
double VO2 = -4.6 + 0.182258*vel + 0.000104*pow(vel, 2);
|
||||
|
||||
// fractional utilization of VO2max for mins duration
|
||||
double FVO2 = 0.8 + 0.1894393*exp(-0.012778*mins) + 0.2989558*exp(-0.1932605*mins);
|
||||
@@ -47,6 +47,24 @@ VDOTCalculator::vVdot(double VDOT)
|
||||
return 29.54 + 5.000663*VDOT - 0.007546*pow(VDOT, 2);
|
||||
}
|
||||
|
||||
double
|
||||
VDOTCalculator::eqvTime(double VDOT, double dist)
|
||||
{
|
||||
// equivalent time for VDOT at dist, estimated by Newton-Raphson method
|
||||
double t = dist/vVdot(VDOT)/0.9; // initial guess at TPace
|
||||
int iter = 100; // max iterations
|
||||
double f_t, fprime_t;
|
||||
|
||||
do {
|
||||
f_t = (0.000104*pow(dist, 2)*pow(t, -2) + 0.182258*dist*pow(t, -1) -4.6)/(0.2989558*exp(-0.1932605*t) + 0.1894393*exp(-0.012778*t) + 0.8) - VDOT;
|
||||
fprime_t = ((0.2989558*exp(-0.1932605*t) + 0.1894393*exp(-0.012778*t) + 0.8)*(-0.000208*pow(dist, 2)*pow(t,-3) - 0.182258*dist*pow(t, -2)) - ((0.000104*pow(dist, 2)*pow(t, -2) + 0.182258*dist*pow(t, -1) -4.6) * (-0.1932605*0.2989558*exp( -0.1932605*t) + -0.012778*0.1894393*exp(-0.012778*t)))) / pow(0.2989558*exp(-0.1932605*t) + 0.1894393*exp(-0.012778*t) + 0.8, 2);
|
||||
t -= f_t/fprime_t;
|
||||
iter--;
|
||||
} while (abs(f_t/fprime_t) > 1e-3 && iter > 0);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
VDOTCalculator::VDOTCalculator(QWidget *parent) : QDialog(parent)
|
||||
{
|
||||
bool metricRnPace = appsettings->value(this, GC_PACE, true).toBool();
|
||||
@@ -57,13 +75,13 @@ VDOTCalculator::VDOTCalculator(QWidget *parent) : QDialog(parent)
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
setFixedSize(300, 450);
|
||||
setFixedSize(300, 480);
|
||||
|
||||
QVBoxLayout *mainVBox = new QVBoxLayout(this);
|
||||
|
||||
mainVBox->addWidget(new QLabel(tr("Your race (1500 to Marathon):")));
|
||||
|
||||
QHBoxLayout *distHBox = new QHBoxLayout;
|
||||
distHBox->addWidget(new QLabel(tr("Your Test Race:")));
|
||||
distHBox->addStretch();
|
||||
distSpinBox = new QDoubleSpinBox(this);
|
||||
distSpinBox->setDecimals(3);
|
||||
if (metricRnPace) {
|
||||
@@ -149,11 +167,45 @@ VDOTCalculator::VDOTCalculator(QWidget *parent) : QDialog(parent)
|
||||
}
|
||||
}
|
||||
tableWidgetTPACE->selectRow(2); // Highlight T-Pace
|
||||
tableWidgetTPACE->resizeRowsToContents();
|
||||
tableLayout->addWidget(tableWidgetTPACE);
|
||||
mainVBox->addLayout(tableLayout);
|
||||
|
||||
mainVBox->addStretch();
|
||||
|
||||
QHBoxLayout *targetHBox = new QHBoxLayout;
|
||||
targetHBox->addWidget(new QLabel(tr("Your Target Race:")));
|
||||
targetHBox->addStretch();
|
||||
targetSpinBox = new QDoubleSpinBox(this);
|
||||
targetSpinBox->setDecimals(3);
|
||||
if (metricRnPace) {
|
||||
targetSpinBox->setRange(1.5, 42.195);
|
||||
targetSpinBox->setSuffix(tr(" km"));
|
||||
targetSpinBox->setValue(21.0975);
|
||||
} else {
|
||||
targetSpinBox->setRange(1.5/KM_PER_MILE, 42.195/KM_PER_MILE);
|
||||
targetSpinBox->setSuffix(tr(" mi"));
|
||||
targetSpinBox->setValue(21.0975/KM_PER_MILE);
|
||||
}
|
||||
targetSpinBox->setSingleStep(1.0);
|
||||
targetSpinBox->setWrapping(false);
|
||||
targetSpinBox->setAlignment(Qt::AlignRight);
|
||||
targetHBox->addWidget(targetSpinBox);
|
||||
targetHBox->addStretch();
|
||||
mainVBox->addLayout(targetHBox);
|
||||
QHBoxLayout *eqvHBox = new QHBoxLayout;
|
||||
eqvHBox->addStretch();
|
||||
labelEQV = new QLabel(tr("Equivalent Time:"));
|
||||
eqvHBox->addWidget(labelEQV);
|
||||
txtEQV = new QLineEdit(this);
|
||||
txtEQV->setAlignment(Qt::AlignRight);
|
||||
txtEQV->setReadOnly(true);
|
||||
eqvHBox->addWidget(txtEQV, Qt::AlignLeft);
|
||||
eqvHBox->addStretch();
|
||||
mainVBox->addLayout(eqvHBox);
|
||||
|
||||
mainVBox->addStretch();
|
||||
|
||||
QHBoxLayout *buttonHBox = new QHBoxLayout;
|
||||
btnCalculate = new QPushButton(this);
|
||||
btnCalculate->setText(tr("Calculate"));
|
||||
@@ -206,4 +258,6 @@ void VDOTCalculator::on_btnCalculate_clicked()
|
||||
tableWidgetTPACE->item(i, 2)->setData(Qt::EditRole, QString("%1")
|
||||
.arg(i < 4 ? QTime(0,0,0).addSecs(pace).toString("mm:ss") : "-----"));
|
||||
}
|
||||
double targetDist = paceFactor*1000*targetSpinBox->value();
|
||||
txtEQV->setText(QTime(0,0,0).addSecs(60*eqvTime(VDOT, targetDist)).toString("hh:mm:ss"));
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ class VDOTCalculator : public QDialog
|
||||
VDOTCalculator(QWidget *parent = 0);
|
||||
static double vdot(double mins, double vel);
|
||||
static double vVdot(double VDOT);
|
||||
static double eqvTime(double VDOT, double dist);
|
||||
|
||||
private:
|
||||
QPushButton *btnCalculate;
|
||||
@@ -46,6 +47,9 @@ class VDOTCalculator : public QDialog
|
||||
QDoubleSpinBox *hoursSpinBox;
|
||||
QDoubleSpinBox *minsSpinBox;
|
||||
QDoubleSpinBox *secsSpinBox;
|
||||
QDoubleSpinBox *targetSpinBox;
|
||||
QLabel *labelEQV;
|
||||
QLineEdit *txtEQV;
|
||||
|
||||
private slots:
|
||||
void on_btnOK_clicked();
|
||||
|
||||
Reference in New Issue
Block a user