diff --git a/src/Metrics/PeakPace.cpp b/src/Metrics/PeakPace.cpp index d59ae3721..7cbebd978 100644 --- a/src/Metrics/PeakPace.cpp +++ b/src/Metrics/PeakPace.cpp @@ -1114,6 +1114,186 @@ class BestTimeMarathon : public BestTime { RideMetric *clone() const { return new BestTimeMarathon(*this); } }; +class PeakPaceHr : public RideMetric { + Q_DECLARE_TR_FUNCTIONS(PeakPaceHr) + + double hr; + double secs; + + public: + + PeakPaceHr() : hr(0.0), secs(0.0) + { + setType(RideMetric::Peak); + } + void setSecs(double secs) { this->secs=secs; } + + void compute(RideItem *item, Specification spec, const QHash &) { + + // no ride or no samples or not a run nor a swim + if (spec.isEmpty(item->ride()) || !(item->isRun || item->isSwim)) { + setValue(RideFile::NIL); + setCount(0); + return; + } + + // find peak pace interval + QList results; + AddIntervalDialog::findPeaks(item->context, true, item->ride(), spec, RideFile::kph, RideFile::original, secs, 1, results, "", ""); + + // work out average hr during that interval + if (results.count() > 0) { + + // start and stop is in seconds within the ride + double start = results.first().start; + double stop = results.first().stop; + int points = 0; + + RideFileIterator it(item->ride(), spec); + while (it.hasNext()) { + struct RideFilePoint *point = it.next(); + if (point->secs >= start && point->secs < stop) { + points++; + hr = (point->hr + (points-1)*hr) / (points); + } + } + } + + setValue(hr); + } + bool isRelevantForRide(const RideItem *ride) const { return ride->isRun || ride->isSwim; } + MetricClass classification() const { return Undefined; } + MetricValidity validity() const { return Unknown; } + RideMetric *clone() const { return new PeakPaceHr(*this); } +}; + +class PeakPaceHr1m : public PeakPaceHr { + Q_DECLARE_TR_FUNCTIONS(PeakPaceHr1m) + + public: + PeakPaceHr1m() + { + setSecs(60); + setSymbol("1m_critical_pace_hr"); + setInternalName("1 min Peak Pace HR"); + } + void initialize () { + setName(tr("1 min Peak Pace HR")); + setMetricUnits(tr("bpm")); + setImperialUnits(tr("bpm")); + setDescription(tr("Average Heart Rate for 1 min Peak Pace interval")); + } + MetricClass classification() const { return Undefined; } + MetricValidity validity() const { return Unknown; } + RideMetric *clone() const { return new PeakPaceHr1m(*this); } +}; + +class PeakPaceHr5m : public PeakPaceHr { + Q_DECLARE_TR_FUNCTIONS(PeakPaceHr5m) + + public: + PeakPaceHr5m() + { + setSecs(300); + setSymbol("5m_critical_pace_hr"); + setInternalName("5 min Peak Pace HR"); + } + void initialize () { + setName(tr("5 min Peak Pace HR")); + setMetricUnits(tr("bpm")); + setImperialUnits(tr("bpm")); + setDescription(tr("Average Heart Rate for 5 min Peak Pace interval")); + } + MetricClass classification() const { return Undefined; } + MetricValidity validity() const { return Unknown; } + RideMetric *clone() const { return new PeakPaceHr5m(*this); } +}; + +class PeakPaceHr10m : public PeakPaceHr { + Q_DECLARE_TR_FUNCTIONS(PeakPaceHr10m) + + public: + PeakPaceHr10m() + { + setSecs(600); + setSymbol("10m_critical_pace_hr"); + setInternalName("10 min Peak Pace HR"); + } + void initialize () { + setName(tr("10 min Peak Pace HR")); + setMetricUnits(tr("bpm")); + setImperialUnits(tr("bpm")); + setDescription(tr("Average Heart Rate for 10 min Peak Pace interval")); + } + MetricClass classification() const { return Undefined; } + MetricValidity validity() const { return Unknown; } + RideMetric *clone() const { return new PeakPaceHr10m(*this); } +}; + +class PeakPaceHr20m : public PeakPaceHr { + Q_DECLARE_TR_FUNCTIONS(PeakPaceHr20m) + + public: + PeakPaceHr20m() + { + setSecs(1200); + setSymbol("20m_critical_pace_hr"); + setInternalName("20 min Peak Pace HR"); + } + void initialize () { + setName(tr("20 min Peak Pace HR")); + setMetricUnits(tr("bpm")); + setImperialUnits(tr("bpm")); + setDescription(tr("Average Heart Rate for 20 min Peak Pace interval")); + } + MetricClass classification() const { return Undefined; } + MetricValidity validity() const { return Unknown; } + RideMetric *clone() const { return new PeakPaceHr20m(*this); } +}; + +class PeakPaceHr30m : public PeakPaceHr { + Q_DECLARE_TR_FUNCTIONS(PeakPaceHr30m) + + public: + PeakPaceHr30m() + { + setSecs(1800); + setSymbol("30m_critical_pace_hr"); + setInternalName("30 min Peak Pace HR"); + } + void initialize () { + setName(tr("30 min Peak Pace HR")); + setMetricUnits(tr("bpm")); + setImperialUnits(tr("bpm")); + setDescription(tr("Average Heart Rate for 30 min Peak Pace interval")); + } + MetricClass classification() const { return Undefined; } + MetricValidity validity() const { return Unknown; } + RideMetric *clone() const { return new PeakPaceHr30m(*this); } +}; + +class PeakPaceHr60m : public PeakPaceHr { + Q_DECLARE_TR_FUNCTIONS(PeakPaceHr30m) + + public: + PeakPaceHr60m() + { + setSecs(3600); + setSymbol("60m_critical_pace_hr"); + setInternalName("60 min Peak Pace HR"); + } + void initialize () { + setName(tr("60 min Peak Pace HR")); + setMetricUnits(tr("bpm")); + setImperialUnits(tr("bpm")); + setDescription(tr("Average Heart Rate for 60 min Peak Pace interval")); + } + MetricClass classification() const { return Undefined; } + MetricValidity validity() const { return Unknown; } + RideMetric *clone() const { return new PeakPaceHr60m(*this); } +}; + + static bool addAllPacePeaks() { RideMetricFactory::instance().addMetric(PeakPace10s()); RideMetricFactory::instance().addMetric(PeakPace15s()); @@ -1165,6 +1345,13 @@ static bool addAllPacePeaks() { RideMetricFactory::instance().addMetric(BestTime40km()); RideMetricFactory::instance().addMetric(BestTimeMarathon()); + RideMetricFactory::instance().addMetric(PeakPaceHr1m()); + RideMetricFactory::instance().addMetric(PeakPaceHr5m()); + RideMetricFactory::instance().addMetric(PeakPaceHr10m()); + RideMetricFactory::instance().addMetric(PeakPaceHr20m()); + RideMetricFactory::instance().addMetric(PeakPaceHr30m()); + RideMetricFactory::instance().addMetric(PeakPaceHr60m()); + return true; } diff --git a/src/Metrics/RideMetric.cpp b/src/Metrics/RideMetric.cpp index b30dbe37e..a70d4dde7 100644 --- a/src/Metrics/RideMetric.cpp +++ b/src/Metrics/RideMetric.cpp @@ -147,7 +147,8 @@ // 137 16 Feb 2017 Leif Warland Added HrvMetrics // 138 01 Mar 2017 Mark Liversedge Added elapsed_time metric for intervals // 139 88 Mar 2017 Leif Warland Added SDANN and SDNNIDX to HRV metrics -int DBSchemaVersion = 139; +// 140 08 Apr 2017 Ale Martinez Added Peak Pace Hr metrics +int DBSchemaVersion = 140; RideMetricFactory *RideMetricFactory::_instance; QVector RideMetricFactory::noDeps; diff --git a/test/charts/VO2_Scores.gchart b/test/charts/VO2_Scores.gchart new file mode 100644 index 000000000..1671be6ea --- /dev/null +++ b/test/charts/VO2_Scores.gchart @@ -0,0 +1,33 @@ +{ + "CHART":{ + "VERSION":"1", + "VIEW":"home", + "TYPE":"7", + "PROPERTIES":{ + "title":"VO2 Scores ", + "subtitle":" ", + "widthFactor":"2", + "heightFactor":"2", + "style":"0", + "resizable":"0", + "preset":"0", + "bin":"2", + "shade":"0", + "data":"0", + "stack":"0", + "stackWidth":"3", + "legend":"1", + "events":"0", + "filter":"search: ", + "fromDate":"Sat Jan 1 2000", + "toDate":"Sat Jan 1 2000", + "startDate":"Thu Jan 5 2017", + "lastN":"7", + "lastNX":"0", + "prevN":"0", + "settings":"/////wAAABgAQwBvAHoAdQBtAGUAbAAgADIAMAAxADAAJXc0AAAAAP8AJXfpAAAAAP8AAAADAAH///////////////8AAAAQAAAAAgAAAAgAAAAAKgAyADAAbQBfAGMAcgBpAHQAaQBjAGEAbABfAHAAbwB3AGUAcgBfAGgAcgAAACgAMgAwACAAbQBpAG4AIABQAGUAYQBrACAAUABvAHcAZQByACAASABSAAAAHABWAE8AMgAgAFMAYwBvAHIAZQAgAEIAaQBrAGUAAAAWAG0AbABPADIALwBtAGkAbgAvAGsAZwAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAd/////8AAAABAf//AAD//wAAAAAAAAAAP/AAAAAAAAAAAAAAAf//AAAAAAAAAAAAAAAAAAAAA+cAAA4Q/////wAAAAoAAAAAAAAAAAAAAAAMADIAIABQAGEAcgBtAAAAAAAAAAAAAA4QAAAAAAAAAAAGAGIAcABtAAABUAAjACAAVgBPADIAIABTAGMAbwByAGUAIABCAGkAawBlAAoAIwAgAGgAdAB0AHAAcwA6AC8ALwBhAGwAYQBuAGMAbwB1AHoAZQBuAHMALgBjAG8AbQAvAGIAbABvAGcALwBWAE8AMgBTAGMAbwByAGUAcwAuAGgAdABtAGwACgA2ADAAXwBtAGkAbgBfAFAAZQBhAGsAXwBQAG8AdwBlAHIALwA3ADUAKgAxADAAMAAwAC8AQQB0AGgAbABlAHQAZQBfAFcAZQBpAGcAaAB0AC8AKAAoADYAMABfAG0AaQBuAF8AUABlAGEAawBfAFAAbwB3AGUAcgBfAEgAUgAtAGMAbwBuAGYAaQBnACgAcgBoAHIAKQApAC8AKABjAG8AbgBmAGkAZwAoAG0AYQB4AGgAcgApAC0AYwBvAG4AZgBpAGcAKAByAGgAcgApACkAKQAAAAIAAABaAGYAaQBsAHQAZQByADoARABhAHQAYQAgAGMAbwBuAHQAYQBpAG4AcwAgACIASAAiACAAJgAmACAARABhAHQAYQAgAGMAbwBuAHQAYQBpAG4AcwAgACIAUAAiAAAACAD/////AAAAAAAAABoAVgBPADIAIABTAGMAbwByAGUAIABSAHUAbgAAABYAbQBsAE8AMgAvAG0AaQBuAC8AawBnAAAAAAABAAAAAAAAAAAAAAAAAQAAf24AAH/+zn+JwAAAAAA0miXA/////wAAAAAB/////1VVAAAAAAAAAAA/8AAAAAAAAAAAAAAB//8AAAAAAAAAAAAAAAAAAAAD5wAADhD/////AAAACgAAAAAAAAAAAAAAAAwAMgAgAFAAYQByAG0AAAAAAAAAAAAADhAAAAAAAP////8AAAEqACMAIABWAE8AMgAgAFMAYwBvAHIAZQAgAFIAdQBuAAoAIwAgAGgAdAB0AHAAcwA6AC8ALwBhAGwAYQBuAGMAbwB1AHoAZQBuAHMALgBjAG8AbQAvAGIAbABvAGcALwBWAE8AMgBTAGMAbwByAGUAcwAuAGgAdABtAGwACgAoADIAMQAwAC8ANgAwAF8AbQBpAG4AXwBQAGUAYQBrAF8AUABhAGMAZQApAC8AKAAoADYAMABfAG0AaQBuAF8AUABlAGEAawBfAFAAYQBjAGUAXwBIAFIALQBjAG8AbgBmAGkAZwAoAHIAaAByACkAKQAvACgAYwBvAG4AZgBpAGcAKABtAGEAeABoAHIAKQAtAGMAbwBuAGYAaQBnACgAcgBoAHIAKQApACkACgAAAAIAAABGAGYAaQBsAHQAZQByADoAaQBzAFIAdQBuAD0AMQAgACYAJgAgAEQAYQB0AGEAIABjAG8AbgB0AGEAaQBuAHMAIAAiAEgAIgAAAAAAAw==", + "useSelected":"0", + "__LAST__":"1", + } + } +} \ No newline at end of file