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 += "| Total workout time: | " +
time_to_string(raw->points.back()->secs);
@@ -214,10 +218,10 @@ RideItem::htmlSummary()
time_to_string(secs_moving_or_pedaling) + " |
";
summary += QString("| Total distance (miles): | "
"%1 |
")
- .arg(raw->points.back()->miles, 0, 'f', 1);
+ .arg(total_distance, 0, 'f', 1);
summary += QString("| Total work (kJ): | "
"%1 |
")
- .arg((unsigned) (avg_watts / 1000.0 * secs_moving_or_pedaling));
+ .arg((unsigned) round(total_work));
summary += QString("| Average speed (mph): | "
"%1 |
")
.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