From 2f0f0d61bfe1b9a511ddb6a62bcd452539263ec8 Mon Sep 17 00:00:00 2001 From: "Sean C. Rhea" Date: Tue, 24 Apr 2007 17:55:40 +0000 Subject: [PATCH] added weekly summary --- src/TODO | 27 -------------- src/gui/MainWindow.cpp | 63 +++++++++++++++++++++++++++++-- src/gui/MainWindow.h | 1 + src/gui/RideItem.cpp | 84 ++++++++++++++++++++++-------------------- src/gui/RideItem.h | 30 ++++++++++----- 5 files changed, 125 insertions(+), 80 deletions(-) diff --git a/src/TODO b/src/TODO index 4bc2292e0..a5e7498e7 100644 --- a/src/TODO +++ b/src/TODO @@ -1,34 +1,7 @@ - - Sort ride into tree list, don't just append - - For cpint, calculate a value for every whole second, using the same or next - largest actual time value from the actual data. That way, SRM and PT - values will align - Pop up an "importing rides" thermometer when importing - - - - - - - Remember last settings for showPower, showHr, etc. - - Add interval summary to ride summary - Switch x-axis from minutes to miles - - Add units to ride summary - - Add weekly summary - - Add cpint - - Power distribution histogram: Rob Carlsen said: - - I believe that it displays the percentage of time that you've spent in - various power ranges, however you can change that to display the - absolute time you've spent in each range. the default is 20 watt - increments, but the recommendation in the book is to decrease the - granularity to 10 watt increments for better estimation of your FTP. - - i thought that using this chart to estimate FTP would only be useful - when there were MANY workout files compiled, rather than looking at - one workout. all the charts on the "athlete home page" of WKO+ seem to - display a collection of past workouts, usually about the last 28 days. - - Power and HR zones diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index ba421105e..58fbee597 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -87,7 +87,7 @@ MainWindow::MainWindow(const QDir &home) : tabWidget = new QTabWidget; rideSummary = new QTextEdit; rideSummary->setReadOnly(true); - tabWidget->addTab(rideSummary, "Ride Summary"); + tabWidget->addTab(rideSummary, tr("Ride Summary")); /////////////////////////// Ride Plot Tab /////////////////////////// @@ -121,15 +121,15 @@ MainWindow::MainWindow(const QDir &home) : QHBoxLayout *smoothLayout = new QHBoxLayout; QLabel *smoothLabel = new QLabel(tr("Smoothing (secs)"), window); smoothLineEdit = new QLineEdit(window); - smoothLineEdit->setFixedWidth(30); + smoothLineEdit->setFixedWidth(40); smoothLayout->addWidget(smoothLabel); smoothLayout->addWidget(smoothLineEdit); smoothSlider = new QSlider(Qt::Horizontal); smoothSlider->setTickPosition(QSlider::TicksBelow); - smoothSlider->setTickInterval(1); + smoothSlider->setTickInterval(10); smoothSlider->setMinimum(2); - smoothSlider->setMaximum(60); + smoothSlider->setMaximum(600); smoothLineEdit->setValidator(new QIntValidator(smoothSlider->minimum(), smoothSlider->maximum(), smoothLineEdit)); @@ -213,6 +213,12 @@ MainWindow::MainWindow(const QDir &home) : tabWidget->addTab(window, "Power Histogram"); + //////////////////////// Power Histogram Tab //////////////////////// + + weeklySummary = new QTextEdit; + weeklySummary->setReadOnly(true); + tabWidget->addTab(weeklySummary, tr("Weekly Summary")); + ////////////////////////////// Signals ////////////////////////////// connect(treeWidget, SIGNAL(itemSelectionChanged()), @@ -432,6 +438,55 @@ MainWindow::rideSelected() if (tabWidget->currentIndex() == 2) cpintPlot->calculate(ride->fileName, ride->dateTime); powerHist->setData(ride->raw); + + QDate wstart = ride->dateTime.date(); + wstart = wstart.addDays(Qt::Monday - wstart.dayOfWeek()); + assert(wstart.dayOfWeek() == Qt::Monday); + QDate wend = wstart.addDays(7); + double weeklySeconds = 0.0; + double weeklyDistance = 0.0; + double weeklyWork = 0.0; + + for (int i = 0; i < allRides->childCount(); ++i) { + if (allRides->child(i)->type() == RIDE_TYPE) { + RideItem *item = (RideItem*) allRides->child(i); + if ((item->dateTime.date() >= wstart) + && (item->dateTime.date() < wend)) { + weeklySeconds += item->secsMovingOrPedaling(); + weeklyDistance += item->totalDistance(); + weeklyWork += item->totalWork(); + } + } + } + + int minutes = ((int) round(weeklySeconds)) / 60; + int hours = (int) minutes / 60; + minutes %= 60; + + const char *dateFormat = "MM/dd/yyyy"; + weeklySummary->setHtml(tr( + "
" + "

Week of %1 through %2

" + "

Summary

" + "

" + "" + "" + " " + "" + " " + "" + " " + "
Total time riding:%3:%4
Total distance (miles):%5
Total work (kJ):%6
" + "

" + ) + .arg(wstart.toString(dateFormat)) + .arg(wstart.addDays(6).toString(dateFormat)) + .arg(hours) + .arg(minutes, 2, 10, QLatin1Char('0')) + .arg((unsigned) round(weeklyDistance)) + .arg((unsigned) round(weeklyWork)) + ); + return; } } diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index f94670951..0eb036532 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -65,6 +65,7 @@ class MainWindow : public QMainWindow QTreeWidget *treeWidget; QTabWidget *tabWidget; QTextEdit *rideSummary; + QTextEdit *weeklySummary; AllPlot *allPlot; CpintPlot *cpintPlot; QLabel *cpintTimeLabel; diff --git a/src/gui/RideItem.cpp b/src/gui/RideItem.cpp index b1ab45c3e..b79875336 100644 --- a/src/gui/RideItem.cpp +++ b/src/gui/RideItem.cpp @@ -62,28 +62,20 @@ static void summarize(QString &intervals, unsigned last_interval, double time_start, double time_end, double mile_start, double mile_end, - unsigned &int_watts_cnt, double &int_watts_sum, - unsigned &int_hr_cnt, double &int_hr_sum, - unsigned &int_cad_cnt, double &int_cad_sum, - unsigned &int_mph_cnt, double &int_mph_sum) { double dur = round(time_end - time_start); double len = mile_end - mile_start; double minutes = (int) (dur/60.0); double seconds = dur - (60 * minutes); - double watts_avg = (int_watts_cnt == 0) ? 0 - : (int) (int_watts_sum / int_watts_cnt); - double hr_avg = (int_hr_cnt == 0) ? 0 - : (int) (int_hr_sum / int_hr_cnt); - double cad_avg = (int_cad_cnt == 0) ? 0 - : (int) (int_cad_sum / int_cad_cnt); - double mph_avg = (int_mph_cnt == 0) ? 0 - : (int) (int_mph_sum / int_mph_cnt); - double energy = watts_avg / 1000.0 * dur; + double watts_avg = int_watts_sum / dur; + double hr_avg = int_hr_sum / dur; + double cad_avg = int_cad_sum / dur; + double mph_avg = int_mph_sum / dur; + double energy = int_watts_sum / 1000.0; // watts_avg / 1000.0 * dur; intervals += "%1"; intervals += "%2:%3"; @@ -103,10 +95,31 @@ static void summarize(QString &intervals, intervals = intervals.arg(cad_avg, 0, 'f', 0); intervals = intervals.arg(mph_avg, 0, 'f', 1); - int_watts_cnt = 0; int_watts_sum = 0.0; - int_hr_cnt = 0; int_hr_sum = 0.0; - int_cad_cnt = 0; int_cad_sum = 0.0; - int_mph_cnt = 0; int_mph_sum = 0.0; + int_watts_sum = 0.0; + int_hr_sum = 0.0; + int_cad_sum = 0.0; + int_mph_sum = 0.0; +} + +double RideItem::secsMovingOrPedaling() +{ + if (summary.isEmpty()) + htmlSummary(); + return secs_moving_or_pedaling; +} + +double RideItem::totalDistance() +{ + if (summary.isEmpty()) + htmlSummary(); + return total_distance; +} + +double RideItem::totalWork() +{ + if (summary.isEmpty()) + htmlSummary(); + return total_work; } QString @@ -124,7 +137,7 @@ RideItem::htmlSummary() return summary; } - double secs_moving_or_pedaling = 0.0; + secs_moving_or_pedaling = 0.0; double secs_moving = 0.0; double total_watts = 0.0; double secs_watts = 0.0; @@ -137,13 +150,9 @@ RideItem::htmlSummary() QString intervals = ""; unsigned last_interval = UINT_MAX; double int_watts_sum = 0.0; - unsigned int_watts_cnt = 0; double int_hr_sum = 0.0; - unsigned int_hr_cnt = 0; double int_cad_sum = 0.0; - unsigned int_cad_cnt = 0; double int_mph_sum = 0.0; - unsigned int_mph_cnt = 0; double time_start, time_end, mile_start, mile_end; @@ -155,10 +164,8 @@ RideItem::htmlSummary() if (last_interval != UINT_MAX) { summarize(intervals, last_interval, time_start, - time_end, mile_start, mile_end, - int_watts_cnt, int_watts_sum, int_hr_cnt, - int_hr_sum, int_cad_cnt, int_cad_sum, - int_mph_cnt, int_mph_sum); + time_end, mile_start, mile_end, int_watts_sum, + int_hr_sum, int_cad_sum, int_mph_sum); } last_interval = point->interval; @@ -174,24 +181,20 @@ RideItem::htmlSummary() if (point->watts >= 0.0) { total_watts += point->watts * secs_delta; secs_watts += secs_delta; - int_watts_sum += point->watts; - int_watts_cnt += 1; + int_watts_sum += point->watts * secs_delta; } if (point->hr > 0) { total_hr += point->hr * secs_delta; secs_hr += secs_delta; - int_hr_sum += point->hr; - int_hr_cnt += 1; + int_hr_sum += point->hr * secs_delta; } if (point->cad > 0) { total_cad += point->cad * secs_delta; secs_cad += secs_delta; - int_cad_sum += point->cad; - int_cad_cnt += 1; + int_cad_sum += point->cad * secs_delta; } if (point->mph >= 0) { - int_mph_sum += point->mph; - int_mph_cnt += 1; + int_mph_sum += point->mph * secs_delta; } mile_end = point->miles; @@ -199,14 +202,15 @@ RideItem::htmlSummary() } summarize(intervals, last_interval, time_start, - time_end, mile_start, mile_end, - int_watts_cnt, int_watts_sum, int_hr_cnt, - int_hr_sum, int_cad_cnt, int_cad_sum, - int_mph_cnt, int_mph_sum); + time_end, mile_start, mile_end, int_watts_sum, + int_hr_sum, int_cad_sum, int_mph_sum); avg_watts = (secs_watts == 0.0) ? 0.0 : round(total_watts / secs_watts); + total_distance = raw->points.back()->miles; + total_work = total_watts / 1000.0; + summary += "

"; summary += ""; summary += QString("" "") - .arg(raw->points.back()->miles, 0, 'f', 1); + .arg(total_distance, 0, 'f', 1); summary += QString("" "") - .arg((unsigned) (avg_watts / 1000.0 * secs_moving_or_pedaling)); + .arg((unsigned) round(total_work)); summary += QString("" "") .arg(((secs_moving == 0.0) ? 0.0 diff --git a/src/gui/RideItem.h b/src/gui/RideItem.h index 58fb8d0ee..f3027a5fd 100644 --- a/src/gui/RideItem.h +++ b/src/gui/RideItem.h @@ -25,17 +25,29 @@ class RawFile; -struct RideItem : public QTreeWidgetItem { - QString path; - QString fileName; - QDateTime dateTime; - QString summary; - RawFile *raw; +class RideItem : public QTreeWidgetItem { - RideItem(QTreeWidgetItem *parent, int type, QString path, - QString fileName, const QDateTime &dateTime); + protected: - QString htmlSummary(); + double secs_moving_or_pedaling; + double total_distance; + double total_work; + + public: + + QString path; + QString fileName; + QDateTime dateTime; + QString summary; + RawFile *raw; + + RideItem(QTreeWidgetItem *parent, int type, QString path, + QString fileName, const QDateTime &dateTime); + + QString htmlSummary(); + double secsMovingOrPedaling(); + double totalDistance(); + double totalWork(); }; #endif // _GC_RideItem_h
Total workout time:" + time_to_string(raw->points.back()->secs); @@ -214,10 +218,10 @@ RideItem::htmlSummary() time_to_string(secs_moving_or_pedaling) + "
Total distance (miles):%1
Total work (kJ):%1
Average speed (mph):%1