From 95e8fcfa090f501fe2f593907720bb14f0c450b2 Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Fri, 6 Jun 2014 00:18:00 +0100 Subject: [PATCH] Show Model Estimates on Summary .. they get refreshed in background so everyone wins ! --- src/MetricAggregator.cpp | 29 ++++++------ src/MetricAggregator.h | 2 +- src/RideSummaryWindow.cpp | 96 +++++++++++++++++++++++++++++++++------ src/RideSummaryWindow.h | 9 ++++ src/src.pro | 2 +- 5 files changed, 109 insertions(+), 29 deletions(-) diff --git a/src/MetricAggregator.cpp b/src/MetricAggregator.cpp index 8a95ec51c..ea7fe188b 100644 --- a/src/MetricAggregator.cpp +++ b/src/MetricAggregator.cpp @@ -465,7 +465,7 @@ MetricAggregator::getRideMetrics(QString filename) } void -MetricAggregator::refreshCPModelMetrics() +MetricAggregator::refreshCPModelMetrics(bool bg) { // this needs to be done once all the other metrics // Calculate a *monthly* estimate of CP, W' etc using @@ -512,14 +512,17 @@ MetricAggregator::refreshCPModelMetrics() // if we have a progress dialog lets update the bar to show // progress for the model parameters -#if (!defined Q_OS_MAC) || (QT_VERSION < 0x050300) // QTBUG 39038 !!! - QProgressDialog *bar = new QProgressDialog(tr("Update Model Estimates"), tr("Abort"), 1, (lastYear*12 + lastMonth) - (year*12 + month)); - bar->setWindowFlags(bar->windowFlags() | Qt::FramelessWindowHint); - bar->setWindowModality(Qt::WindowModal); - bar->setMinimumDuration(0); - bar->setValue(1); - bar->show(); // lets hide until elapsed time is > 6 seconds - QApplication::processEvents(); +#if (!defined Q_OS_MAC) || (defined QT_NOBUG39038) || (QT_VERSION < 0x050300) // QTBUG 39038 !!! + QProgressDialog *bar; + if (!bg) { + bar = new QProgressDialog(tr("Update Model Estimates"), tr("Abort"), 1, (lastYear*12 + lastMonth) - (year*12 + month)); + bar->setWindowFlags(bar->windowFlags() | Qt::FramelessWindowHint); + bar->setWindowModality(Qt::WindowModal); + bar->setMinimumDuration(0); + bar->setValue(1); + bar->show(); // lets hide until elapsed time is > 6 seconds + QApplication::processEvents(); + } #endif QList< QVector > months; @@ -604,12 +607,12 @@ MetricAggregator::refreshCPModelMetrics() month ++; } -#if (!defined Q_OS_MAC) || (QT_VERSION < 0x050300) +#if (!defined Q_OS_MAC) || (defined QT_NOBUG39038) || (QT_VERSION < 0x050300) // QTBUG 39038 !!! // show some progress - bar->setValue(count); + if (!bg) bar->setValue(count); #endif } -#if (!defined Q_OS_MAC) || (QT_VERSION < 0x050300) - delete bar; +#if (!defined Q_OS_MAC) || (defined QT_NOBUG39038) || (QT_VERSION < 0x050300) // QTBUG 39038 !!! + if (!bg) delete bar; #endif } diff --git a/src/MetricAggregator.h b/src/MetricAggregator.h index 4056b2d34..fa077ff13 100644 --- a/src/MetricAggregator.h +++ b/src/MetricAggregator.h @@ -47,7 +47,7 @@ class MetricAggregator : public QObject void refreshMetrics(); void refreshMetrics(QDateTime forceAfterThisDate); - void refreshCPModelMetrics(); // metrics derived from model + void refreshCPModelMetrics(bool bg=false); // metrics derived from model void getFirstLast(QDate &, QDate &); DBAccess *db() { return dbaccess; } diff --git a/src/RideSummaryWindow.cpp b/src/RideSummaryWindow.cpp index 94fdbed42..9f3a1cbec 100644 --- a/src/RideSummaryWindow.cpp +++ b/src/RideSummaryWindow.cpp @@ -26,6 +26,7 @@ #include "TimeUtils.h" #include "Units.h" #include "Zones.h" +#include "PDModel.h" #include "MetricAggregator.h" #include "DBAccess.h" #include @@ -106,6 +107,9 @@ RideSummaryWindow::RideSummaryWindow(Context *context, bool ridesummary) : connect(dateSetting, SIGNAL(useThruToday()), this, SLOT(useThruToday())); connect(dateSetting, SIGNAL(useStandardRange()), this, SLOT(useStandardRange())); + // concurrent callback to refresh + connect(this, SIGNAL(doRefresh()), this, SLOT(refresh())); + } connect(context, SIGNAL(configChanged()), this, SLOT(configChanged())); setChartLayout(vlayout); @@ -536,20 +540,22 @@ RideSummaryWindow::htmlSummary() summary += ""; } -//XXX TOO SLOW -- NEED TO THINK ABOUT DOING THIS IN BACKGROUND -#if 0 // now add in the model parameters if we are not in ridesummary mode... // if we're summarising a range we need to get the model parameters refreshed if (!ridesummary && bestsCache == NULL) { - // update the model if neccessary - bestsCache = new RideFileCache(context, current.from, current.to, filtered, filters, true); + // get the PDEStimates for this athlete + if (context->athlete->PDEstimates.count() == 0) { - // use sensible intervals for parameter selection - cpModel = ecp->deriveExtendedCP_5_3_Parameters(true, bestsCache, - RideFile::watts, 20.0f/60.0f, 90.0f/60.0f, 120.0f/60.0f, - 300.0f/60.0f, 600.0f/60.0f, 3000.0f/60.0f, 4000.0f/60.0f, - 30000.0f/60.0f); + // ugh .. refresh in background + WPrimeString = CPString = FTPString = PMaxString = "-"; + QFuture future = QtConcurrent::run(this, &RideSummaryWindow::getPDEstimates); + + } else { + + // set from cached values + getPDEstimates(); + } // lets get a table going summary += "" @@ -560,26 +566,25 @@ RideSummaryWindow::htmlSummary() // W; summary += QString("") .arg("W' (kJ)") - .arg(cpModel.etau * cpModel.ecp * 60.0f / 1000.0, 0, 'f', 1); + .arg(WPrimeString); // CP; summary += QString("") .arg("CP (watts)") - .arg(int(cpModel.ecp)); + .arg(CPString); // FTP/MMP60; summary += QString("") .arg("FTP / MMP60 (watts)") - .arg(int(cpModel.mmp60)); + .arg(FTPString); // Pmax; summary += QString("") .arg("P-max (watts)") - .arg(int(cpModel.pMax)); + .arg(PMaxString); summary += "
%1:%2
%1:%2
%1:%2
%1:%2
"; } -#endif summary += ""; @@ -958,6 +963,69 @@ RideSummaryWindow::htmlSummary() return summary; } +void +RideSummaryWindow::getPDEstimates() +{ + bool ping = false; + double lowWPrime=0, highWPrime=0, + lowCP=0, highCP=0, + lowFTP=0, highFTP=0, + lowPMax=0, highPMax=0; + + // refresh if needed + if (context->athlete->PDEstimates.count() == 0) { + ping = true; + context->athlete->metricDB->refreshCPModelMetrics(true); //true = bg ... + } + + // loop through and get ... + foreach(PDEstimate est, context->athlete->PDEstimates) { + + // We only use the extended model for now + if (est.model != "Ext" || est.from > myDateRange.to || est.to < myDateRange.from) continue; + + // it definitely was during our period + if ((est.from >= myDateRange.from && est.from <= myDateRange.to) || (est.to >= myDateRange.from && est.to <= myDateRange.to) || + (est.from <= myDateRange.from && est.to >= myDateRange.to)) { + + // set low + if (!lowWPrime || est.WPrime < lowWPrime) lowWPrime = est.WPrime; + if (!lowCP || est.CP < lowCP) lowCP = est.CP; + if (!lowFTP || est.FTP < lowFTP) lowFTP = est.FTP; + if (!lowPMax || est.PMax < lowPMax) lowPMax = est.PMax; + + // set high + if (!highWPrime || est.WPrime > highWPrime) highWPrime = est.WPrime; + if (!highCP || est.CP > highCP) highCP = est.CP; + if (!highFTP || est.FTP > highFTP) highFTP = est.FTP; + if (!highPMax || est.PMax > highPMax) highPMax = est.PMax; + } + } + + // ok, so lets set the string to either + // N/A => when its not available + // low - high => when its a range + // val => when low = high + if (!lowWPrime && !highWPrime) WPrimeString = "N/A"; + else if (lowWPrime != highWPrime) WPrimeString = QString ("%1 - %2").arg(lowWPrime/1000, 0, 'f', 1).arg(highWPrime/1000, 0, 'f', 1); + else WPrimeString = QString("%1").arg(highWPrime/1000, 0, 'f', 1); + + if (!lowCP && !highCP) CPString = "N/A"; + else if (lowCP != highCP) CPString = QString ("%1 - %2").arg(lowCP).arg(highCP); + else CPString = QString("%1").arg(highCP); + + if (!lowFTP && !highFTP) FTPString = "N/A"; + else if (lowFTP != highFTP) FTPString = QString ("%1 - %2").arg(lowFTP).arg(highFTP); + else FTPString = QString("%1").arg(highFTP); + + if (!lowPMax && !highPMax) PMaxString = "N/A"; + else if (lowPMax != highPMax) PMaxString = QString ("%1 - %2").arg(lowPMax).arg(highPMax); + else PMaxString = QString("%1").arg(highPMax); + + // now refresh ! + if (ping) emit doRefresh(); +} + QString RideSummaryWindow::htmlCompareSummary() const { diff --git a/src/RideSummaryWindow.h b/src/RideSummaryWindow.h index 532d36b53..53db11848 100644 --- a/src/RideSummaryWindow.h +++ b/src/RideSummaryWindow.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "SummaryMetrics.h" #include "RideFileCache.h" @@ -83,6 +84,8 @@ class RideSummaryWindow : public GcChartWindow bool isCompare() const { return ((ridesummary && context->isCompareIntervals) || (!ridesummary && context->isCompareDateRanges)); } + void getPDEstimates(); + protected slots: void refresh(); @@ -107,6 +110,10 @@ class RideSummaryWindow : public GcChartWindow // config changed void configChanged(); + signals: + + void doRefresh(); + protected: QString htmlSummary(); // summary of a ride or a date range @@ -135,6 +142,8 @@ class RideSummaryWindow : public GcChartWindow ExtendedCriticalPower *ecp; Model_eCP cpModel; + QString WPrimeString, CPString, FTPString, PMaxString; + bool force; // to force a replot }; diff --git a/src/src.pro b/src/src.pro index 48d46992e..ed04c4031 100644 --- a/src/src.pro +++ b/src/src.pro @@ -21,7 +21,7 @@ LIBS += -lm $${LIBZ_LIBS} # 5.2.0 or higher # ## common modules -QT += xml sql network script svg +QT += xml sql network script svg concurrent lessThan(QT_MAJOR_VERSION, 5) {