mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 00:28:42 +00:00
Interval : Add Search for Peak Speed, Peak Pace
This commit is contained in:
@@ -398,6 +398,17 @@ RideFile::unitName(SeriesType series, Context *context)
|
||||
}
|
||||
}
|
||||
|
||||
QString
|
||||
RideFile::formatValueWithUnit(double value, SeriesType series, Conversion conversion, Context *context, bool isSwim)
|
||||
{
|
||||
bool useMetricUnits = context->athlete->useMetricUnits;
|
||||
|
||||
if (series == RideFile::kph && conversion == RideFile::pace)
|
||||
return kphToPace(value, useMetricUnits, isSwim);
|
||||
else
|
||||
return QString("%1%2").arg(value).arg(unitName(series, context));
|
||||
}
|
||||
|
||||
void
|
||||
RideFile::clearIntervals()
|
||||
{
|
||||
|
||||
@@ -202,11 +202,14 @@ class RideFile : public QObject // QObject to emit signals
|
||||
wbal, tcore,
|
||||
none }; // none must ALWAYS be last
|
||||
|
||||
enum conversion { original, pace };
|
||||
|
||||
// NA = Not Applicable - i.e Temperature no recorded value
|
||||
// NIL = Not available, but still set to zero for compatibility
|
||||
// We should consider looking at code to handle NIL / NA
|
||||
enum specialValues { NA = -255, NIL = 0 };
|
||||
typedef enum seriestype SeriesType;
|
||||
typedef enum conversion Conversion;
|
||||
static SeriesType lastSeriesType() { return none; }
|
||||
|
||||
static QStringList symbols(); // get a list of symbols for each series to use in a formula
|
||||
@@ -215,6 +218,8 @@ class RideFile : public QObject // QObject to emit signals
|
||||
|
||||
static QString seriesName(SeriesType, bool compat=false);
|
||||
static QString unitName(SeriesType, Context *context);
|
||||
static QString formatValueWithUnit(double value, SeriesType series, Conversion conversion, Context *context, bool isSwim);
|
||||
|
||||
static int decimalsFor(SeriesType series);
|
||||
static double maximumFor(SeriesType series);
|
||||
static double minimumFor(SeriesType series);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "Settings.h"
|
||||
#include "Athlete.h"
|
||||
#include "Context.h"
|
||||
#include "Units.h"
|
||||
#include "IntervalItem.h"
|
||||
#include "RideFile.h"
|
||||
#include "RideItem.h"
|
||||
@@ -53,10 +54,10 @@ AddIntervalDialog::AddIntervalDialog(Context *context) :
|
||||
intervalMethodLayout->addLayout(methodRadios);
|
||||
intervalMethodLayout->addStretch();
|
||||
|
||||
methodBestPower = new QRadioButton(tr("Peak Power"));
|
||||
methodBestPower->setChecked(true);
|
||||
methodButtonGroup->addButton(methodBestPower);
|
||||
methodRadios->addWidget(methodBestPower);
|
||||
methodPeakPower = new QRadioButton(tr("Peak Power"));
|
||||
methodPeakPower->setChecked(true);
|
||||
methodButtonGroup->addButton(methodPeakPower);
|
||||
methodRadios->addWidget(methodPeakPower);
|
||||
|
||||
methodClimb = new QRadioButton(tr("Ascent (elevation)"));
|
||||
methodClimb->setChecked(false);
|
||||
@@ -68,16 +69,26 @@ AddIntervalDialog::AddIntervalDialog(Context *context) :
|
||||
methodButtonGroup->addButton(methodWPrime);
|
||||
methodRadios->addWidget(methodWPrime);
|
||||
|
||||
methodFirst = new QRadioButton(tr("Time / Distance"));
|
||||
methodFirst->setChecked(false);
|
||||
methodButtonGroup->addButton(methodFirst);
|
||||
methodRadios->addWidget(methodFirst);
|
||||
|
||||
methodHeartRate = new QRadioButton(tr("Heart rate"));
|
||||
methodHeartRate->setChecked(false);
|
||||
methodButtonGroup->addButton(methodHeartRate);
|
||||
methodRadios->addWidget(methodHeartRate);
|
||||
|
||||
methodPeakSpeed = new QRadioButton(tr("Peak Speed"));
|
||||
methodPeakSpeed->setChecked(false);
|
||||
methodButtonGroup->addButton(methodPeakSpeed);
|
||||
methodRadios->addWidget(methodPeakSpeed);
|
||||
|
||||
methodPeakPace = new QRadioButton(tr("Peak Pace"));
|
||||
methodPeakPace->setChecked(false);
|
||||
methodButtonGroup->addButton(methodPeakPace);
|
||||
methodRadios->addWidget(methodPeakPace);
|
||||
|
||||
methodFirst = new QRadioButton(tr("Time / Distance"));
|
||||
methodFirst->setChecked(false);
|
||||
methodButtonGroup->addButton(methodFirst);
|
||||
methodRadios->addWidget(methodFirst);
|
||||
|
||||
intervalPeakPowerWidget = new QWidget();
|
||||
intervalPeakPowerTypeLayout = new QHBoxLayout;
|
||||
intervalPeakPowerTypeLayout->addStretch();
|
||||
@@ -252,10 +263,12 @@ AddIntervalDialog::AddIntervalDialog(Context *context) :
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
|
||||
connect(methodFirst, SIGNAL(clicked()), this, SLOT(methodFirstClicked()));
|
||||
connect(methodBestPower, SIGNAL(clicked()), this, SLOT(methodBestPowerClicked()));
|
||||
connect(methodPeakPower, SIGNAL(clicked()), this, SLOT(methodPeakPowerClicked()));
|
||||
connect(methodWPrime, SIGNAL(clicked()), this, SLOT(methodWPrimeClicked()));
|
||||
connect(methodClimb, SIGNAL(clicked()), this, SLOT(methodClimbClicked()));
|
||||
connect(methodHeartRate, SIGNAL(clicked()), this, SLOT(methodHeartRateClicked()));
|
||||
connect(methodPeakPace, SIGNAL(clicked()), this, SLOT(methodPeakPaceClicked()));
|
||||
connect(methodPeakSpeed, SIGNAL(clicked()), this, SLOT(methodPeakSpeedClicked()));
|
||||
connect(peakPowerStandard, SIGNAL(clicked()), this, SLOT(peakPowerStandardClicked()));
|
||||
connect(peakPowerCustom, SIGNAL(clicked()), this, SLOT(peakPowerCustomClicked()));
|
||||
connect(typeTime, SIGNAL(clicked()), this, SLOT(typeTimeClicked()));
|
||||
@@ -264,7 +277,7 @@ AddIntervalDialog::AddIntervalDialog(Context *context) :
|
||||
connect(addButton, SIGNAL(clicked()), this, SLOT(addClicked()));
|
||||
|
||||
// get set to default to best powers (peaks)
|
||||
methodBestPowerClicked();
|
||||
methodPeakPowerClicked();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -285,7 +298,7 @@ AddIntervalDialog::methodFirstClicked()
|
||||
}
|
||||
|
||||
void
|
||||
AddIntervalDialog::methodBestPowerClicked()
|
||||
AddIntervalDialog::methodPeakPowerClicked()
|
||||
{
|
||||
// clear the table
|
||||
clearResultsTable(resultsTable);
|
||||
@@ -293,6 +306,7 @@ AddIntervalDialog::methodBestPowerClicked()
|
||||
intervalWPrimeWidget->hide();
|
||||
intervalPeakPowerWidget->show();
|
||||
intervalClimbWidget->hide();
|
||||
|
||||
if (peakPowerCustom->isChecked())
|
||||
peakPowerCustomClicked();
|
||||
else
|
||||
@@ -329,6 +343,42 @@ AddIntervalDialog::methodClimbClicked()
|
||||
intervalWPrimeWidget->hide();
|
||||
}
|
||||
|
||||
void
|
||||
AddIntervalDialog::methodPeakSpeedClicked()
|
||||
{
|
||||
// clear the table
|
||||
clearResultsTable(resultsTable);
|
||||
|
||||
intervalClimbWidget->hide();
|
||||
intervalPeakPowerWidget->hide();
|
||||
intervalWPrimeWidget->hide();
|
||||
|
||||
intervalTypeWidget->show();
|
||||
if (typeDistance->isChecked())
|
||||
typeDistanceClicked();
|
||||
else
|
||||
typeTimeClicked();
|
||||
intervalCountWidget->show();
|
||||
}
|
||||
|
||||
void
|
||||
AddIntervalDialog::methodPeakPaceClicked()
|
||||
{
|
||||
// clear the table
|
||||
clearResultsTable(resultsTable);
|
||||
|
||||
intervalClimbWidget->hide();
|
||||
intervalPeakPowerWidget->hide();
|
||||
intervalWPrimeWidget->hide();
|
||||
|
||||
intervalTypeWidget->show();
|
||||
if (typeDistance->isChecked())
|
||||
typeDistanceClicked();
|
||||
else
|
||||
typeTimeClicked();
|
||||
intervalCountWidget->show();
|
||||
}
|
||||
|
||||
void
|
||||
AddIntervalDialog::methodHeartRateClicked()
|
||||
{
|
||||
@@ -337,11 +387,13 @@ AddIntervalDialog::methodHeartRateClicked()
|
||||
|
||||
intervalClimbWidget->hide();
|
||||
intervalPeakPowerWidget->hide();
|
||||
intervalTypeWidget->hide();
|
||||
intervalDistanceWidget->hide();
|
||||
intervalWPrimeWidget->hide();
|
||||
|
||||
intervalTimeWidget->show();
|
||||
intervalTypeWidget->show();
|
||||
if (typeDistance->isChecked())
|
||||
typeDistanceClicked();
|
||||
else
|
||||
typeTimeClicked();
|
||||
intervalCountWidget->show();
|
||||
}
|
||||
|
||||
@@ -464,9 +516,10 @@ AddIntervalDialog::createClicked()
|
||||
QList<AddedInterval> results;
|
||||
|
||||
// FIND PEAKS
|
||||
if (methodBestPower->isChecked()) {
|
||||
if (methodPeakPower->isChecked() || methodPeakSpeed->isChecked() ||
|
||||
methodPeakPace->isChecked() || methodHeartRate->isChecked()) {
|
||||
|
||||
if (peakPowerStandard->isChecked())
|
||||
if (methodPeakPower->isChecked() && peakPowerStandard->isChecked())
|
||||
findPeakPowerStandard(context, ride, results);
|
||||
else {
|
||||
|
||||
@@ -476,10 +529,20 @@ AddIntervalDialog::createClicked()
|
||||
return;
|
||||
}
|
||||
|
||||
findBests(context, byTime, ride, RideFile::watts, (byTime?windowSizeSecs:windowSizeMeters), maxIntervals, results, "");
|
||||
if (methodPeakPower->isChecked()) {
|
||||
findPeaks(context, byTime, ride, RideFile::watts, RideFile::original, (byTime?windowSizeSecs:windowSizeMeters), maxIntervals, results, "Peak Power","");
|
||||
}
|
||||
else if (methodPeakSpeed->isChecked()) {
|
||||
findPeaks(context, byTime, ride, RideFile::kph, RideFile::original, (byTime?windowSizeSecs:windowSizeMeters), maxIntervals, results, "Peak Speed","");
|
||||
}
|
||||
else if (methodPeakPace->isChecked()) {
|
||||
findPeaks(context, byTime, ride, RideFile::kph, RideFile::pace, (byTime?windowSizeSecs:windowSizeMeters), maxIntervals, results, "Peak Pace", "");
|
||||
}
|
||||
else if (methodHeartRate->isChecked()) {
|
||||
findPeaks(context, byTime, ride, RideFile::hr, RideFile::original, (byTime?windowSizeSecs:windowSizeMeters), maxIntervals, results, "Peak HR", "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// FIND PEAKS
|
||||
@@ -491,11 +554,12 @@ AddIntervalDialog::createClicked()
|
||||
return;
|
||||
}
|
||||
|
||||
findBests(context, byTime, ride, RideFile::hr, (byTime?windowSizeSecs:windowSizeMeters), maxIntervals, results, "");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// FIND BY TIME OR DISTANCE
|
||||
if (methodFirst->isChecked()) {
|
||||
|
||||
@@ -761,22 +825,23 @@ AddIntervalDialog::findFirsts(bool typeTime, const RideFile *ride, double window
|
||||
void
|
||||
AddIntervalDialog::findPeakPowerStandard(Context *context, const RideFile *ride, QList<AddedInterval> &results)
|
||||
{
|
||||
findBests(context, true, ride, RideFile::watts, 5, 1, results, tr("Peak 5s"));
|
||||
findBests(context, true, ride, RideFile::watts, 10, 1, results, tr("Peak 10s"));
|
||||
findBests(context, true, ride, RideFile::watts, 20, 1, results, tr("Peak 20s"));
|
||||
findBests(context, true, ride, RideFile::watts, 30, 1, results, tr("Peak 30s"));
|
||||
findBests(context, true, ride, RideFile::watts, 60, 1, results, tr("Peak 1min"));
|
||||
findBests(context, true, ride, RideFile::watts, 120, 1, results, tr("Peak 2min"));
|
||||
findBests(context, true, ride, RideFile::watts, 300, 1, results, tr("Peak 5min"));
|
||||
findBests(context, true, ride, RideFile::watts, 600, 1, results, tr("Peak 10min"));
|
||||
findBests(context, true, ride, RideFile::watts, 1200, 1, results, tr("Peak 20min"));
|
||||
findBests(context, true, ride, RideFile::watts, 1800, 1, results, tr("Peak 30min"));
|
||||
findBests(context, true, ride, RideFile::watts, 3600, 1, results, tr("Peak 60min"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 5, 1, results, "", tr("Peak 5s"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 10, 1, results, "", tr("Peak 10s"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 20, 1, results, "", tr("Peak 20s"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 30, 1, results, "", tr("Peak 30s"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 60, 1, results, "", tr("Peak 1min"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 120, 1, results, "", tr("Peak 2min"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 300, 1, results, "", tr("Peak 5min"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 600, 1, results, "", tr("Peak 10min"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 1200, 1, results, "", tr("Peak 20min"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 1800, 1, results, "", tr("Peak 30min"));
|
||||
findPeaks(context, true, ride, RideFile::watts, RideFile::original, 3600, 1, results, "", tr("Peak 60min"));
|
||||
}
|
||||
|
||||
void
|
||||
AddIntervalDialog::findBests(Context *context, bool typeTime, const RideFile *ride, RideFile::SeriesType series, double windowSize,
|
||||
int maxIntervals, QList<AddedInterval> &results, QString prefix)
|
||||
AddIntervalDialog::findPeaks(Context *context, bool typeTime, const RideFile *ride,
|
||||
RideFile::SeriesType series, RideFile::Conversion conversion, double windowSize,
|
||||
int maxIntervals, QList<AddedInterval> &results, QString prefixe, QString overideName)
|
||||
{
|
||||
QList<AddedInterval> bests;
|
||||
QList<AddedInterval> _results;
|
||||
@@ -824,11 +889,14 @@ AddIntervalDialog::findBests(Context *context, bool typeTime, const RideFile *ri
|
||||
}
|
||||
}
|
||||
if (!overlaps) {
|
||||
QString name = prefix;
|
||||
if (prefix == "") {
|
||||
QString name = overideName;
|
||||
if (overideName == "") {
|
||||
name = tr("%1 %3%4 #%2");
|
||||
|
||||
name = name.arg("Peak");
|
||||
if (prefixe == "")
|
||||
name = name.arg(tr("Peak"));
|
||||
else
|
||||
name = name.arg(prefixe);
|
||||
|
||||
name = name.arg(_results.count()+1);
|
||||
if (typeTime) {
|
||||
@@ -878,8 +946,9 @@ AddIntervalDialog::findBests(Context *context, bool typeTime, const RideFile *ri
|
||||
}
|
||||
}
|
||||
}
|
||||
name += " (%4%5)";
|
||||
name = name.arg(round(candidate.avg)).arg(ride->unitName(series, context));
|
||||
name += " (%4)";
|
||||
name = name.arg(ride->formatValueWithUnit(round(candidate.avg), series, conversion, context, ride->isSwim()));
|
||||
|
||||
candidate.name = name;
|
||||
name = "";
|
||||
_results.append(candidate);
|
||||
|
||||
@@ -52,8 +52,9 @@ class AddIntervalDialog : public QDialog
|
||||
|
||||
static void findPeakPowerStandard(Context *context, const RideFile *ride, QList<AddedInterval> &results);
|
||||
|
||||
static void findBests(Context *context, bool typeTime, const RideFile *ride, RideFile::SeriesType series, double windowSizeSecs,
|
||||
int maxIntervals, QList<AddedInterval> &results, QString name);
|
||||
static void findPeaks(Context *context, bool typeTime, const RideFile *ride, RideFile::SeriesType series,
|
||||
RideFile::Conversion conversion, double windowSizeSecs,
|
||||
int maxIntervals, QList<AddedInterval> &results, QString prefixe, QString overideName);
|
||||
|
||||
static void findFirsts(bool typeTime, const RideFile *ride, double windowSizeSecs,
|
||||
int maxIntervals, QList<AddedInterval> &results);
|
||||
@@ -63,10 +64,12 @@ class AddIntervalDialog : public QDialog
|
||||
void addClicked(); // add to inverval selections
|
||||
|
||||
void methodFirstClicked();
|
||||
void methodBestPowerClicked();
|
||||
void methodPeakPowerClicked();
|
||||
void methodWPrimeClicked();
|
||||
void methodClimbClicked();
|
||||
void methodHeartRateClicked();
|
||||
void methodPeakPaceClicked();
|
||||
void methodPeakSpeedClicked();
|
||||
void peakPowerStandardClicked();
|
||||
void peakPowerCustomClicked();
|
||||
void typeTimeClicked();
|
||||
@@ -84,7 +87,8 @@ class AddIntervalDialog : public QDialog
|
||||
QPushButton *createButton, *addButton;
|
||||
QDoubleSpinBox *hrsSpinBox, *minsSpinBox, *secsSpinBox, *altSpinBox,
|
||||
*countSpinBox,*kmsSpinBox, *msSpinBox, *kjSpinBox;
|
||||
QRadioButton *methodFirst, *methodBestPower, *methodWPrime, *methodClimb, *methodHeartRate;
|
||||
QRadioButton *methodFirst, *methodPeakPower, *methodWPrime, *methodClimb, *methodHeartRate,
|
||||
*methodPeakSpeed, *methodPeakPace;
|
||||
QRadioButton *typeDistance, *typeTime, *peakPowerStandard, *peakPowerCustom;
|
||||
QTableWidget *resultsTable;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user