Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VO2 and Ventilation graphs to WorkoutWidget and add settings #3415

Merged
merged 2 commits into from Apr 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/Gui/Colors.cpp
Expand Up @@ -229,6 +229,12 @@ void GCColor::setupColors()
#endif
{ tr("Overview Background"), "COVERVIEWBACKGROUND", QColor(0,0,0) },
{ tr("Overview Card Background"), "CCARDBACKGROUND", QColor(52,52,52) },
{ tr("VO2"), "CVO2", Qt::magenta },
{ tr("Ventilation"), "CVENTILATION", Qt::cyan },
{ tr("VCO2"), "CVCO2", Qt::green },
{ tr("Tidal Volume"), "CTIDALVOLUME", Qt::yellow },
{ tr("Respiratory Frequency"), "CRESPFREQUENCY", Qt::yellow },
{ tr("FeO2"), "CFEO2", Qt::yellow },
{ "", "", QColor(0,0,0) },
};

Expand Down
8 changes: 7 additions & 1 deletion src/Gui/Colors.h
Expand Up @@ -162,7 +162,7 @@ class ColorEngine : public QObject
#define GColor(x) GCColor::getColor(x)

// Define how many cconfigurable metric colors are available
#define CNUMOFCFGCOLORS 98
#define CNUMOFCFGCOLORS 104

#define CPLOTBACKGROUND 0
#define CRIDEPLOTBACKGROUND 1
Expand Down Expand Up @@ -262,4 +262,10 @@ class ColorEngine : public QObject
#define CCHROME 95
#define COVERVIEWBACKGROUND 96
#define CCARDBACKGROUND 97
#define CVO2 98
#define CVENTILATION 99
#define CVCO2 100
#define CTIDALVOLUME 101
#define CRESPFREQUENCY 102
#define CFEO2 103
#endif
27 changes: 22 additions & 5 deletions src/Train/DialWindow.cpp
Expand Up @@ -589,16 +589,33 @@ void DialWindow::seriesChanged()
case RealtimeData::VI:
case RealtimeData::SkibaVI:
case RealtimeData::Slope:
case RealtimeData::FeO2:
foreground = GColor(CFEO2);
break;
case RealtimeData::RER:
case RealtimeData::None:
foreground = GColor(CDIAL);
break;

case RealtimeData::Rf:
foreground = GColor(CRESPFREQUENCY);
break;

case RealtimeData::RMV:
foreground = GColor(CVENTILATION);
break;

case RealtimeData::VO2:
foreground = GColor(CVO2);
break;

case RealtimeData::VCO2:
case RealtimeData::RER:
foreground = GColor(CVCO2);
break;

case RealtimeData::TidalVolume:
case RealtimeData::FeO2:
case RealtimeData::None:
foreground = GColor(CDIAL);
break;
foreground = GColor(CTIDALVOLUME);
break;

case RealtimeData::Load:
foreground = GColor(CLOAD);
Expand Down
2 changes: 1 addition & 1 deletion src/Train/RealtimeData.cpp
Expand Up @@ -639,7 +639,7 @@ QString RealtimeData::seriesName(DataSeries series)
case Rf: return tr("Respiratory Frequency");
break;

case RMV: return tr("Respiratory Minute Volume");
case RMV: return tr("Ventilation");
break;

case VO2: return tr("VO2");
Expand Down
121 changes: 113 additions & 8 deletions src/Train/WorkoutWidget.cpp
Expand Up @@ -23,7 +23,6 @@

#include "WPrime.h"
#include "ErgFile.h"
#include "RideFile.h"
#include "RideFileCache.h"
#include "RealtimeData.h"

Expand Down Expand Up @@ -96,6 +95,8 @@ WorkoutWidget::WorkoutWidget(WorkoutWindow *parent, Context *context) :
cadenceMax = 200; // make it line up between power and hr
hrMax = 220;
speedMax = 50;
vo2Max = 5000;
ventilationMax = 130;

onDrag = onCreate = onRect = atRect = QPointF(-1,-1);
qwkactive = false;
Expand Down Expand Up @@ -150,14 +151,18 @@ WorkoutWidget::start()
speed.clear();
cadence.clear();
sampleTimes.clear();
vo2.clear();
ventilation.clear();

// and resampling data
count = wbalSum = wattsSum = hrSum = speedSum = cadenceSum =0;
count = wbalSum = wattsSum = hrSum = speedSum = cadenceSum = vo2Sum = ventilationSum = 0;

// set initial
cadenceMax = 200;
hrMax = 220;
speedMax = 50;
vo2Max = 5000;
ventilationMax = 130;

// replot
update();
Expand Down Expand Up @@ -187,6 +192,8 @@ WorkoutWidget::telemetryUpdate(RealtimeData rt)
hrSum += rt.getHr();
cadenceSum += rt.getCadence();
speedSum += rt.getSpeed();
vo2Sum += rt.getVO2();
ventilationSum += rt.getRMV();

count++;

Expand All @@ -202,15 +209,21 @@ WorkoutWidget::telemetryUpdate(RealtimeData rt)
speed << s;
int c = cadenceSum / 5.0f;
cadence << c;
int v = vo2Sum / 5.0f;
vo2 << v;
int ve = ventilationSum / 5.0f;
ventilation << ve;
sampleTimes << context->getNow();

// clear for next time
count = wbalSum = wattsSum = hrSum = speedSum = cadenceSum =0;
count = wbalSum = wattsSum = hrSum = speedSum = cadenceSum = vo2Sum = ventilationSum = 0;

// do we need to increase maxes?
if (c > cadenceMax) cadenceMax=c;
if (s > speedMax) speedMax=s;
if (h > hrMax) hrMax=h;
if (v > vo2Max) vo2Max=v;
if (ve > ventilationMax) ventilationMax=ve;

// Do we need to increase plot x-axis max? (add 15 min at a time)
if (cadence.size() > maxVX_) setMaxVX(maxVX_ + 900);
Expand Down Expand Up @@ -2445,7 +2458,7 @@ WorkoutWidget::logX(double t)

// transform from plot to painter co-ordinate
QPoint
WorkoutWidget::transform(double seconds, double watts, RideFile::SeriesType s)
WorkoutWidget::transform(double seconds, double watts, WwSeriesType s)
{
// from plot coords to painter coords on the canvas
QRectF c = canvas();
Expand All @@ -2456,34 +2469,48 @@ WorkoutWidget::transform(double seconds, double watts, RideFile::SeriesType s)
switch (s) {

default:
case RideFile::watts:
case POWER:
{
// ratio of pixels to plot units
yratio = double(c.height()) / (maxY()-minY());
}
break;

case RideFile::hr:
case HEARTRATE:
{
// ratio of pixels to plot units
yratio = double(c.height()) / double(hrMax);
}
break;

case RideFile::cad:
case CADENCE:
{
// ratio of pixels to plot units
yratio = double(c.height()) / double(cadenceMax);
}
break;

case RideFile::kph:
case SPEED:
{
// ratio of pixels to plot units
yratio = double(c.height()) / double(speedMax);
}
break;

case VO2:
{
// ratio of pixels to plot units
yratio = double(c.height()) / double(vo2Max);
}
break;

case VENTILATION:
{
// ratio of pixels to plot units
yratio = double(c.height()) / double(ventilationMax);
}
break;

}
return QPoint(c.x() - (minVX() * xratio) + (seconds * xratio), c.bottomLeft().y() - (watts * yratio));
}
Expand Down Expand Up @@ -2938,3 +2965,81 @@ WorkoutWidget::paste()
// update the display
update();
}

bool
WorkoutWidget::shouldPlotHr()
{
return parent->shouldPlotHr();
}

bool
WorkoutWidget::shouldPlotPwr()
{
return parent->shouldPlotPwr();
}

bool
WorkoutWidget::shouldPlotCadence()
{
return parent->shouldPlotCadence();
}

bool
WorkoutWidget::shouldPlotWbal()
{
return parent->shouldPlotWbal();
}

bool
WorkoutWidget::shouldPlotVo2()
{
return parent->shouldPlotVo2();
}

bool
WorkoutWidget::shouldPlotVentilation()
{
return parent->shouldPlotVentilation();
}

bool
WorkoutWidget::shouldPlotSpeed()
{
return parent->shouldPlotSpeed();
}

int
WorkoutWidget::hrPlotAvgLength()
{
return parent->hrPlotAvgLength();
}

int
WorkoutWidget::pwrPlotAvgLength()
{
return parent->pwrPlotAvgLength();
}

int
WorkoutWidget::cadencePlotAvgLength()
{
return parent->cadencePlotAvgLength();
}

int
WorkoutWidget::vo2PlotAvgLength()
{
return parent->vo2PlotAvgLength();
}

int
WorkoutWidget::ventilationPlotAvgLength()
{
return parent->ventilationPlotAvgLength();
}

int
WorkoutWidget::speedPlotAvgLength()
{
return parent->speedPlotAvgLength();
}
29 changes: 27 additions & 2 deletions src/Train/WorkoutWidget.h
Expand Up @@ -25,7 +25,6 @@

#include "WPrime.h"

#include "RideFile.h"
#include "Settings.h"
#include "Units.h"
#include "Colors.h"
Expand Down Expand Up @@ -135,6 +134,9 @@ class WorkoutWidget : public QWidget
QList<int> hr; // 1s samples [bpm]
QList<double> speed; // 1s samples [km/h]
QList<int> cadence; // 1s samples [rpm]
QList<int> vo2; // 1s samples [ml/min]
QList<int> ventilation; // 1s samples [l/min]
QList<double> hrAvg, pwrAvg, cadenceAvg, vo2Avg, ventilationAvg, speedAvg; // averages

// interaction state;
// none - initial state
Expand All @@ -144,6 +146,9 @@ class WorkoutWidget : public QWidget
// create - clicked to create
enum { none, create, drag, dragblock, rect } state;

enum wwseriestype { CADENCE, HEARTRATE, POWER, SPEED, WBAL, VO2, VENTILATION };
typedef enum wwseriestype WwSeriesType;

// adding items and points
void addItem(WorkoutWidgetItem*x) { children_.append(x); }
void addPoint(WWPoint*x) { points_.append(x); }
Expand Down Expand Up @@ -193,7 +198,7 @@ class WorkoutWidget : public QWidget
}

// transform from plot to painter co-ordinate
QPoint transform(double x, double y, RideFile::SeriesType s=RideFile::watts);
QPoint transform(double x, double y, WwSeriesType s=POWER);

// for log(x) scale
int logX(double t);
Expand Down Expand Up @@ -294,6 +299,22 @@ class WorkoutWidget : public QWidget
// hate this function !
bool setBlockCursor();

// settings getters
bool shouldPlotHr();
bool shouldPlotPwr();
bool shouldPlotCadence();
bool shouldPlotWbal();
bool shouldPlotVo2();
bool shouldPlotVentilation();
bool shouldPlotSpeed();

int hrPlotAvgLength();
int pwrPlotAvgLength();
int cadencePlotAvgLength();
int vo2PlotAvgLength();
int ventilationPlotAvgLength();
int speedPlotAvgLength();

protected:

// interacting with points
Expand Down Expand Up @@ -384,13 +405,17 @@ class WorkoutWidget : public QWidget
int cadenceMax;
int hrMax;
double speedMax;
int vo2Max;
int ventilationMax;

// resampling when recording
double wbalSum;
double wattsSum;
double cadenceSum;
double speedSum;
double hrSum;
double vo2Sum;
double ventilationSum;
int count;
};

Expand Down