mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 16:39:57 +00:00
215 lines
8.0 KiB
C++
215 lines
8.0 KiB
C++
/*
|
|
* Copyright (c) 2007 Justin F. Knotzke (jknotzke@shampoo.ca)
|
|
*
|
|
* 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 "ToolsDialog.h"
|
|
#include "HelpWhatsThis.h"
|
|
#include "Settings.h"
|
|
|
|
QHBoxLayout*
|
|
ToolsDialog::setupMinsSecs(QDoubleSpinBoxPtr &minsSpinBox,
|
|
QDoubleSpinBoxPtr &secsSpinBox,
|
|
QDoubleSpinBoxPtr &wattsSpinBox,
|
|
double maxMin, double defaultMin)
|
|
{
|
|
QHBoxLayout *result = new QHBoxLayout;
|
|
minsSpinBox = new QDoubleSpinBox(this);
|
|
minsSpinBox->setDecimals(0);
|
|
minsSpinBox->setRange(0.0, maxMin);
|
|
minsSpinBox->setSuffix(tr(" mins"));
|
|
minsSpinBox->setSingleStep(1.0);
|
|
minsSpinBox->setWrapping(false);
|
|
minsSpinBox->setAlignment(Qt::AlignRight);
|
|
minsSpinBox->setValue(defaultMin);
|
|
result->addWidget(minsSpinBox);
|
|
secsSpinBox = new QDoubleSpinBox(this);
|
|
secsSpinBox->setDecimals(0);
|
|
secsSpinBox->setRange(0.0, 59.0);
|
|
secsSpinBox->setSuffix(tr(" secs"));
|
|
secsSpinBox->setSingleStep(1.0);
|
|
secsSpinBox->setWrapping(true);
|
|
secsSpinBox->setAlignment(Qt::AlignRight);
|
|
result->addWidget(secsSpinBox);
|
|
wattsSpinBox = new QDoubleSpinBox(this);
|
|
wattsSpinBox->setDecimals(0);
|
|
wattsSpinBox->setRange(0.0, 3000.0);
|
|
wattsSpinBox->setSuffix(tr(" watts"));
|
|
wattsSpinBox->setSingleStep(1.0);
|
|
wattsSpinBox->setWrapping(false);
|
|
wattsSpinBox->setAlignment(Qt::AlignRight);
|
|
result->addWidget(wattsSpinBox);
|
|
return result;
|
|
}
|
|
|
|
ToolsDialog::ToolsDialog(QWidget *parent) : QDialog(parent)
|
|
{
|
|
setWindowTitle(tr("Critical Power Estimator"));
|
|
|
|
HelpWhatsThis *help = new HelpWhatsThis(this);
|
|
this->setWhatsThis(help->getWhatsThisText(HelpWhatsThis::MenuBar_Tools_CP_EST));
|
|
|
|
setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
setFixedSize(300, 300);
|
|
|
|
QVBoxLayout *mainVBox = new QVBoxLayout(this);
|
|
|
|
QHBoxLayout *hlayout = new QHBoxLayout;
|
|
QLabel *sportLabel = new QLabel(tr("Sport"));
|
|
sportCombo = new QComboBox();
|
|
sportCombo->addItem(tr("Bike"));
|
|
sportCombo->addItem(tr("Run"));
|
|
sportCombo->addItem(tr("Swim"));
|
|
sportCombo->setCurrentIndex(0);
|
|
hlayout->addStretch();
|
|
hlayout->addWidget(sportLabel);
|
|
hlayout->addWidget(sportCombo);
|
|
hlayout->addStretch();
|
|
mainVBox->addLayout(hlayout);
|
|
|
|
mainVBox->addWidget(new QLabel(tr("Your best short effort (3-5 min):")));
|
|
mainVBox->addLayout(setupMinsSecs(shortMinsSpinBox, shortSecsSpinBox,
|
|
shortWattsSpinBox, 5.0, 3.0));
|
|
|
|
mainVBox->addWidget(new QLabel(tr("Your best long effort (15-60 min):")));
|
|
mainVBox->addLayout(setupMinsSecs(longMinsSpinBox, longSecsSpinBox,
|
|
longWattsSpinBox, 60.0, 20.0));
|
|
mainVBox->addStretch();
|
|
|
|
QHBoxLayout *cpHBox = new QHBoxLayout;
|
|
cpHBox->addStretch();
|
|
labelCP = new QLabel(tr("Your critical power:"));
|
|
cpHBox->addWidget(labelCP);
|
|
txtCP = new QLineEdit(this);
|
|
txtCP->setAlignment(Qt::AlignRight);
|
|
txtCP->setReadOnly(true);
|
|
cpHBox->addWidget(txtCP, Qt::AlignLeft);
|
|
cpHBox->addStretch();
|
|
mainVBox->addLayout(cpHBox);
|
|
|
|
QHBoxLayout *wpHBox = new QHBoxLayout;
|
|
wpHBox->addStretch();
|
|
labelWP = new QLabel(tr("Your W':"));
|
|
wpHBox->addWidget(labelWP);
|
|
txtWP = new QLineEdit(this);
|
|
txtWP->setAlignment(Qt::AlignRight);
|
|
txtWP->setReadOnly(true);
|
|
wpHBox->addWidget(txtWP, Qt::AlignLeft);
|
|
wpHBox->addStretch();
|
|
mainVBox->addLayout(wpHBox);
|
|
|
|
mainVBox->addStretch();
|
|
|
|
QHBoxLayout *buttonHBox = new QHBoxLayout;
|
|
btnCalculate = new QPushButton(this);
|
|
btnCalculate->setText(tr("Estimate"));
|
|
buttonHBox->addStretch();
|
|
buttonHBox->addWidget(btnCalculate);
|
|
btnOK = new QPushButton(this);
|
|
btnOK->setText(tr("Done"));
|
|
buttonHBox->addWidget(btnOK);
|
|
mainVBox->addLayout(buttonHBox);
|
|
|
|
connect(sportCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSport()));
|
|
connect(btnOK, SIGNAL(clicked()), this, SLOT(on_btnOK_clicked()));
|
|
connect(btnCalculate, SIGNAL(clicked()), this, SLOT(on_btnCalculate_clicked()));
|
|
}
|
|
|
|
void
|
|
ToolsDialog::changeSport()
|
|
{
|
|
QString rnSuffix = appsettings->value(this, GC_PACE, true).toBool() ? tr(" km") : tr(" mi");
|
|
QString swSuffix = appsettings->value(this, GC_SWIMPACE, true).toBool() ? tr(" m") : tr(" yd");
|
|
switch (sportCombo->currentIndex()) {
|
|
case 0: // Bike
|
|
shortWattsSpinBox->setDecimals(0);
|
|
shortWattsSpinBox->setSuffix(tr(" watts"));
|
|
longWattsSpinBox->setDecimals(0);
|
|
longWattsSpinBox->setSuffix(tr(" watts"));
|
|
labelCP->setText(tr("Your critical power:"));
|
|
labelWP->setText(tr("Your W':"));
|
|
break;
|
|
case 1: // Run
|
|
shortWattsSpinBox->setDecimals(1);
|
|
shortWattsSpinBox->setSuffix(rnSuffix);
|
|
longWattsSpinBox->setDecimals(1);
|
|
longWattsSpinBox->setSuffix(rnSuffix);
|
|
labelCP->setText(tr("Your critical pace:"));
|
|
labelWP->setText(tr("Your D':"));
|
|
break;
|
|
case 2: // Swim
|
|
shortWattsSpinBox->setDecimals(0);
|
|
shortWattsSpinBox->setSuffix(swSuffix);
|
|
longWattsSpinBox->setDecimals(0);
|
|
longWattsSpinBox->setSuffix(swSuffix);
|
|
labelCP->setText(tr("Your critical pace:"));
|
|
labelWP->setText(tr("Your D':"));
|
|
break;
|
|
}
|
|
shortWattsSpinBox->clear();
|
|
longWattsSpinBox->clear();
|
|
txtCP->clear();
|
|
txtWP->clear();
|
|
}
|
|
|
|
void ToolsDialog::on_btnOK_clicked()
|
|
{
|
|
accept();
|
|
}
|
|
|
|
void ToolsDialog::on_btnCalculate_clicked()
|
|
{
|
|
bool metricRnPace = appsettings->value(this, GC_PACE, true).toBool();
|
|
bool metricSwPace = appsettings->value(this, GC_PACE, true).toBool();
|
|
double shortSecs =
|
|
shortMinsSpinBox->value() * 60.0 + shortSecsSpinBox->value();
|
|
double shortWatts = shortWattsSpinBox->value();
|
|
double longSecs =
|
|
longMinsSpinBox->value() * 60.0 + longSecsSpinBox->value();
|
|
double longWatts = longWattsSpinBox->value();
|
|
double CP;
|
|
double Wprime;
|
|
switch (sportCombo->currentIndex()) {
|
|
case 0: // Bike
|
|
CP = (longSecs * longWatts - shortSecs * shortWatts)
|
|
/ (longSecs - shortSecs);
|
|
txtCP->setText(tr("%1 watts").arg(static_cast<int>(round(CP))));
|
|
|
|
Wprime = ((shortSecs * (shortWatts-CP)) +
|
|
(longSecs * (longWatts-CP))) /2;
|
|
txtWP->setText(tr("%1 kJ").arg(static_cast<int>(round(Wprime/1000))));
|
|
break;
|
|
case 1: // Run
|
|
CP = (longSecs - shortSecs) / (longWatts - shortWatts);
|
|
txtCP->setText(QString("%1 %2").arg(QTime(0,0,0).addSecs(CP).toString("mm:ss")).arg(metricRnPace ? tr("min/km") : tr("min/mi")));
|
|
|
|
Wprime = ((shortWatts-shortSecs/CP) +
|
|
(longWatts-longSecs/CP)) /2;
|
|
txtWP->setText(QString("%1 %2").arg(round(Wprime*1000)/1000).arg(metricRnPace ? tr("km") : tr("mi")));
|
|
break;
|
|
case 2: // Swim
|
|
CP = 100 * (longSecs - shortSecs) / (longWatts - shortWatts);
|
|
txtCP->setText(QString("%1 %2").arg(QTime(0,0,0).addSecs(CP).toString("mm:ss")).arg(metricSwPace ? tr("min/100m") : tr("min/100yd")));
|
|
|
|
Wprime = ((shortWatts-100*shortSecs/CP) +
|
|
(longWatts-100*longSecs/CP)) /2;
|
|
txtWP->setText(QString("%1 %2").arg(round(Wprime)).arg(metricSwPace ? tr("m") : tr("yd")));
|
|
break;
|
|
}
|
|
}
|
|
|